LCOV - code coverage report
Current view: top level - sw/source/filter/writer - wrtswtbl.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 227 390 58.2 %
Date: 2014-04-11 Functions: 17 24 70.8 %
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        1649 : sal_Int16 SwWriteTableCell::GetVertOri() const
      36             : {
      37        1649 :     sal_Int16 eCellVertOri = text::VertOrientation::TOP;
      38        1649 :     if( pBox->GetSttNd() )
      39             :     {
      40        1649 :         const SfxItemSet& rItemSet = pBox->GetFrmFmt()->GetAttrSet();
      41             :         const SfxPoolItem *pItem;
      42        1649 :         if( SFX_ITEM_SET == rItemSet.GetItemState( RES_VERT_ORIENT, false, &pItem ) )
      43             :         {
      44             :             sal_Int16 eBoxVertOri =
      45         417 :                 ((const SwFmtVertOrient *)pItem)->GetVertOrient();
      46         417 :             if( text::VertOrientation::CENTER==eBoxVertOri || text::VertOrientation::BOTTOM==eBoxVertOri)
      47         417 :                 eCellVertOri = eBoxVertOri;
      48             :         }
      49             :     }
      50             : 
      51        1649 :     return eCellVertOri;
      52             : }
      53             : 
      54        1246 : SwWriteTableRow::SwWriteTableRow( long nPosition, bool bUseLayoutHeights )
      55             :     : pBackground(0), nPos(nPosition), mbUseLayoutHeights(bUseLayoutHeights),
      56             :     nTopBorder(USHRT_MAX), nBottomBorder(USHRT_MAX), bTopBorder(true),
      57        1246 :     bBottomBorder(true)
      58             : {
      59        1246 : }
      60             : 
      61        1832 : 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        1832 :                                 nHeight, pBackgroundBrush );
      70        1832 :     aCells.push_back( pCell );
      71             : 
      72        1832 :     return pCell;
      73             : }
      74             : 
      75        3154 : SwWriteTableCol::SwWriteTableCol(sal_uInt32 nPosition)
      76             :     : nPos(nPosition), nWidthOpt(0), bRelWidthOpt(false), bOutWidth(true),
      77        3154 :     bLeftBorder(true), bRightBorder(true)
      78             : {
      79        3154 : }
      80             : 
      81        2418 : sal_uInt32 SwWriteTable::GetBoxWidth( const SwTableBox *pBox )
      82             : {
      83        2418 :     const SwFrmFmt *pFmt = pBox->GetFrmFmt();
      84             :     const SwFmtFrmSize& aFrmSize=
      85        2418 :         (const SwFmtFrmSize&)pFmt->GetFmtAttr( RES_FRM_SIZE );
      86             : 
      87        2418 :     return sal::static_int_cast<sal_uInt32>(aFrmSize.GetSize().Width());
      88             : }
      89             : 
      90        1246 : long SwWriteTable::GetLineHeight( const SwTableLine *pLine )
      91             : {
      92             : #ifdef DBG_UTIL
      93             :     bool bOldGetLineHeightCalled = m_bGetLineHeightCalled;
      94             :     m_bGetLineHeightCalled = true;
      95             : #endif
      96             : 
      97        1246 :     long nHeight = 0;
      98        1246 :     if( bUseLayoutHeights )
      99             :     {
     100             :         // At first we try to get the height of the layout.
     101        1186 :         bool bLayoutAvailable = false;
     102        1186 :         nHeight = pLine->GetTableLineHeight(bLayoutAvailable);
     103        1186 :         if( nHeight > 0 )
     104        1140 :             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          46 :         bUseLayoutHeights = bLayoutAvailable;
     111             : 
     112             : #ifdef DBG_UTIL
     113             :         SAL_WARN_IF( !bLayoutAvailable && bOldGetLineHeightCalled, "sw", "Layout invalid?" );
     114             : #endif
     115             :     }
     116             : 
     117         106 :     const SwTableBoxes& rBoxes = pLine->GetTabBoxes();
     118         106 :     sal_uInt16 nBoxes = rBoxes.size();
     119             : 
     120         474 :     for( sal_uInt16 nBox=0; nBox<nBoxes; nBox++ )
     121             :     {
     122         368 :         const SwTableBox* pBox = rBoxes[nBox];
     123         368 :         if( pBox->GetSttNd() )
     124             :         {
     125         368 :             if( nHeight < ROW_DFLT_HEIGHT )
     126         106 :                 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         106 :     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, 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, 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        5345 : void SwWriteTable::MergeBorders( const SvxBorderLine* pBorderLine,
     194             :                                    bool bTable )
     195             : {
     196        5345 :     if( (sal_uInt32)-1 == nBorderColor )
     197             :     {
     198          79 :         Color aGrayColor( COL_GRAY );
     199          79 :         if( !pBorderLine->GetColor().IsRGBEqual( aGrayColor ) )
     200          79 :             nBorderColor = pBorderLine->GetColor().GetColor();
     201             :     }
     202             : 
     203        5345 :     if( !bCollectBorderWidth )
     204        5345 :         return;
     205             : 
     206        5345 :     sal_uInt16 nOutWidth = pBorderLine->GetOutWidth();
     207        5345 :     if( bTable )
     208             :     {
     209        1389 :         if( nOutWidth && (!nBorder || nOutWidth < nBorder) )
     210          78 :             nBorder = nOutWidth;
     211             :     }
     212             :     else
     213             :     {
     214        3956 :         if( nOutWidth && (!nInnerBorder || nOutWidth < nInnerBorder) )
     215          72 :             nInnerBorder = nOutWidth;
     216             :     }
     217             : 
     218        5345 :     sal_uInt16 nDist = pBorderLine->GetInWidth() ? pBorderLine->GetDistance()
     219        5345 :                                                 : 0;
     220        5345 :     if( nDist && (!nCellSpacing || nDist < nCellSpacing) )
     221           2 :         nCellSpacing = nDist;
     222             : }
     223             : 
     224        1832 : 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        1832 :     sal_uInt16 nBorderMask = 0;
     231             : 
     232        1832 :     const SwFrmFmt *pFrmFmt = pBox->GetFrmFmt();
     233        1832 :     const SvxBoxItem& rBoxItem = (const SvxBoxItem&)pFrmFmt->GetFmtAttr( RES_BOX );
     234             : 
     235        1832 :     if( rBoxItem.GetTop() )
     236             :     {
     237        1359 :         nBorderMask |= 1;
     238        1359 :         MergeBorders( rBoxItem.GetTop(), nRow==0 );
     239        1359 :         rTopBorder = rBoxItem.GetTop()->GetOutWidth();
     240             :     }
     241             : 
     242        1832 :     if( rBoxItem.GetLeft() )
     243             :     {
     244        1330 :         nBorderMask |= 4;
     245        1330 :         MergeBorders( rBoxItem.GetLeft(), nCol==0 );
     246             :     }
     247             : 
     248        1832 :     if( rBoxItem.GetBottom() )
     249             :     {
     250        1399 :         nBorderMask |= 2;
     251        1399 :         MergeBorders( rBoxItem.GetBottom(), nRow+nRowSpan==aRows.size() );
     252        1399 :         rBottomBorder = rBoxItem.GetBottom()->GetOutWidth();
     253             :     }
     254             : 
     255        1832 :     if( rBoxItem.GetRight() )
     256             :     {
     257        1257 :         nBorderMask |= 8;
     258        1257 :         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        1832 :     if( bCollectBorderWidth )
     265             :     {
     266        1832 :         sal_uInt16 nDist = rBoxItem.GetDistance( BOX_LINE_TOP );
     267        1832 :         if( nDist && (!nCellPadding || nDist < nCellPadding) )
     268          33 :             nCellPadding = nDist;
     269        1832 :         nDist = rBoxItem.GetDistance( BOX_LINE_BOTTOM );
     270        1832 :         if( nDist && (!nCellPadding || nDist < nCellPadding) )
     271           0 :             nCellPadding = nDist;
     272        1832 :         nDist = rBoxItem.GetDistance( BOX_LINE_LEFT );
     273        1832 :         if( nDist && (!nCellPadding || nDist < nCellPadding) )
     274          70 :             nCellPadding = nDist;
     275        1832 :         nDist = rBoxItem.GetDistance( BOX_LINE_RIGHT );
     276        1832 :         if( nDist && (!nCellPadding || nDist < nCellPadding) )
     277          35 :             nCellPadding = nDist;
     278             :     }
     279             : 
     280        1832 :     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        3664 : sal_Bool SwWriteTable::ShouldExpandSub(const SwTableBox *pBox, sal_Bool /*bExpandedBefore*/,
     391             :     sal_uInt16 nDepth) const
     392             : {
     393        3664 :     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         113 : 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         113 :     sal_Bool bSubExpanded = sal_False;
     408         113 :     sal_uInt16 nLines = rLines.size();
     409             : 
     410             : #if OSL_DEBUG_LEVEL > 0
     411             :     sal_uInt32 nEndCPos = 0;
     412             : #endif
     413             : 
     414         113 :     long nRPos = nStartRPos;
     415         736 :     for( sal_uInt16 nLine = 0; nLine < nLines; nLine++ )
     416             :     {
     417         623 :         /*const*/ SwTableLine *pLine = rLines[nLine];
     418             : 
     419         623 :         long nOldRPos = nRPos;
     420             : 
     421         623 :         if( nLine < nLines-1 || nParentLineHeight==0  )
     422             :         {
     423         623 :             long nLineHeight = GetLineHeight( pLine );
     424         623 :             nRPos += nLineHeight;
     425         623 :             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         623 :             SwWriteTableRow *pRow = new SwWriteTableRow( nRPos, bUseLayoutHeights);
     438         623 :             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           0 :             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         623 :         const SwTableBoxes& rBoxes = pLine->GetTabBoxes();
     460         623 :         sal_uInt16 nBoxes = rBoxes.size();
     461             : 
     462         623 :         sal_uInt32 nCPos = nStartCPos;
     463        2455 :         for( sal_uInt16 nBox=0; nBox<nBoxes; nBox++ )
     464             :         {
     465        1832 :             const SwTableBox *pBox = rBoxes[nBox];
     466             : 
     467        1832 :             sal_uInt32 nOldCPos = nCPos;
     468             : 
     469        1832 :             if( nBox < nBoxes-1 || (nParentLineWidth==0 && nLine==0)  )
     470             :             {
     471        1209 :                 nCPos = nCPos + GetBoxWidth( pBox );
     472        1209 :                 SwWriteTableCol *pCol = new SwWriteTableCol( nCPos );
     473             : 
     474        1209 :                 if( !aCols.insert( pCol ).second )
     475         961 :                     delete pCol;
     476             : 
     477        1209 :                 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        1209 :                 }
     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         623 :                 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        1832 :             if( ShouldExpandSub( pBox, bSubExpanded, nDepth ) )
     512             :             {
     513             :                 CollectTableRowsCols( nOldRPos, nOldCPos,
     514             :                                         nRPos - nOldRPos,
     515             :                                         nCPos - nOldCPos,
     516           0 :                                         pBox->GetTabLines(),
     517           0 :                                         nDepth-1 );
     518           0 :                 bSubExpanded = sal_True;
     519             :             }
     520             :         }
     521             :     }
     522         113 : }
     523             : 
     524         113 : 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         113 :     sal_uInt16 nLines = rLines.size();
     534         113 :     sal_Bool bSubExpanded = sal_False;
     535             : 
     536             :     // Specifying the border
     537         113 :     long nRPos = nStartRPos;
     538         113 :     sal_uInt16 nRow = nStartRow;
     539             : 
     540         736 :     for( sal_uInt16 nLine = 0; nLine < nLines; nLine++ )
     541             :     {
     542         623 :         const SwTableLine *pLine = rLines[nLine];
     543             : 
     544             :         // Determine the position of the last covered row
     545         623 :         long nOldRPos = nRPos;
     546         623 :         if( nLine < nLines-1 || nParentLineHeight==0 )
     547             :         {
     548         623 :             long nLineHeight = GetLineHeight( pLine );
     549         623 :             nRPos += nLineHeight;
     550         623 :             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         623 :             }
     559             :         }
     560             :         else
     561           0 :             nRPos = nStartRPos + nParentLineHeight;
     562             : 
     563             :         // And their index
     564         623 :         sal_uInt16 nOldRow = nRow;
     565         623 :         SwWriteTableRow aSrchRow( nRPos,bUseLayoutHeights );
     566         623 :         SwWriteTableRows::const_iterator it2 = aRows.find( &aSrchRow );
     567             : 
     568             :         // coupled methods out of sync ...
     569             :         assert( it2 != aRows.end() );
     570         623 :         nRow = it2 - aRows.begin();
     571             : 
     572             :         OSL_ENSURE( nOldRow <= nRow, "Don't look back!" );
     573         623 :         if( nOldRow > nRow )
     574             :         {
     575           0 :             nOldRow = nRow;
     576           0 :             if( nOldRow )
     577           0 :                 --nOldRow;
     578             :         }
     579             : 
     580         623 :         SwWriteTableRow *pRow = aRows[nOldRow];
     581         623 :         SwWriteTableRow *pEndRow = aRows[nRow];
     582         623 :         if( nLine+1==nNumOfHeaderRows && nParentLineHeight==0 )
     583           0 :             nHeadEndRow = nRow;
     584             : 
     585         623 :         const SwTableBoxes& rBoxes = pLine->GetTabBoxes();
     586             : 
     587         623 :         const SwFrmFmt *pLineFrmFmt = pLine->GetFrmFmt();
     588             :         const SfxPoolItem* pItem;
     589         623 :         const SfxItemSet& rItemSet = pLineFrmFmt->GetAttrSet();
     590             : 
     591         623 :         long nHeight = 0;
     592         623 :         if( SFX_ITEM_SET == rItemSet.GetItemState( RES_FRM_SIZE, true, &pItem ))
     593         270 :             nHeight = ((SwFmtFrmSize*)pItem)->GetHeight();
     594             : 
     595         623 :         const SvxBrushItem *pBrushItem, *pLineBrush = pParentBrush;
     596         623 :         if( SFX_ITEM_SET == rItemSet.GetItemState( RES_BACKGROUND, false,
     597         623 :                                                    &pItem ) )
     598             :         {
     599           0 :             pLineBrush = (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 :             sal_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         623 :             pRow->SetBackground( pLineBrush );
     621         623 :             pBrushItem = 0;
     622             :         }
     623             : 
     624         623 :         sal_uInt16 nBoxes = rBoxes.size();
     625         623 :         sal_uInt32 nCPos = nStartCPos;
     626         623 :         sal_uInt16 nCol = nStartCol;
     627             : 
     628        2455 :         for( sal_uInt16 nBox=0; nBox<nBoxes; nBox++ )
     629             :         {
     630        1832 :             const SwTableBox *pBox = rBoxes[nBox];
     631             : 
     632             :             // Determine the position of the last covered column
     633        1832 :             sal_uInt32 nOldCPos = nCPos;
     634        1832 :             if( nBox < nBoxes-1 || (nParentLineWidth==0 && nLine==0) )
     635             :             {
     636        1209 :                 nCPos = nCPos + GetBoxWidth( pBox );
     637        2418 :                 if( nBox==nBoxes-1 )
     638           0 :                     nParentLineWidth = nCPos - nStartCPos;
     639             :             }
     640             :             else
     641         623 :                 nCPos = nStartCPos + nParentLineWidth;
     642             : 
     643             :             // And their index
     644        1832 :             sal_uInt16 nOldCol = nCol;
     645        1832 :             SwWriteTableCol aSrchCol( nCPos );
     646        1832 :             SwWriteTableCols::const_iterator it = aCols.find( &aSrchCol );
     647             :             OSL_ENSURE( it != aCols.end(), "missing column" );
     648        1832 :             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        1832 :                 nCol = it - aCols.begin();
     652             :             }
     653             : 
     654        1832 :             if( !ShouldExpandSub( pBox, bSubExpanded, nDepth ) )
     655             :             {
     656        1832 :                 sal_uInt16 nRowSpan = nRow - nOldRow + 1;
     657             : 
     658             :                 // The new table model may have true row span attributes
     659        1832 :                 const long nAttrRowSpan = pBox->getRowSpan();
     660        1832 :                 if ( 1 < nAttrRowSpan )
     661          12 :                     nRowSpan = (sal_uInt16)nAttrRowSpan;
     662        1820 :                 else if ( nAttrRowSpan < 1 )
     663          12 :                     nRowSpan = 0;
     664             : 
     665        1832 :                 sal_uInt16 nColSpan = nCol - nOldCol + 1;
     666             :                 pRow->AddCell( pBox, nOldRow, nOldCol,
     667             :                                nRowSpan, nColSpan, nHeight,
     668        1832 :                                pBrushItem );
     669        1832 :                 nHeight = 0; // The height requires only to be written once
     670             : 
     671        1832 :                 if( pBox->GetSttNd() )
     672             :                 {
     673        1832 :                     sal_uInt16 nTopBorder = USHRT_MAX, nBottomBorder = USHRT_MAX;
     674             :                     sal_uInt16 nBorderMask = MergeBoxBorders(pBox, nOldRow, nOldCol,
     675        1832 :                         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        1832 :                     if (!(nBorderMask & 4) && nOldCol < aCols.size())
     681             :                     {
     682         502 :                         SwWriteTableCol *pCol = aCols[nOldCol];
     683             :                         OSL_ENSURE(pCol, "No TableCol found, panic!");
     684         502 :                         if (pCol)
     685         502 :                             pCol->bLeftBorder = false;
     686             :                     }
     687             : 
     688        1832 :                     if (!(nBorderMask & 8))
     689             :                     {
     690         575 :                         SwWriteTableCol *pCol = aCols[nCol];
     691             :                         OSL_ENSURE(pCol, "No TableCol found, panic!");
     692         575 :                         if (pCol)
     693         575 :                             pCol->bRightBorder = false;
     694             :                     }
     695             : 
     696        1832 :                     if (!(nBorderMask & 1))
     697         473 :                         pRow->bTopBorder = false;
     698        1359 :                     else if (!pRow->nTopBorder || nTopBorder < pRow->nTopBorder)
     699         463 :                         pRow->nTopBorder = nTopBorder;
     700             : 
     701        1832 :                     if (!(nBorderMask & 2))
     702         433 :                         pEndRow->bBottomBorder = false;
     703        1399 :                     else if (
     704        2798 :                                 !pEndRow->nBottomBorder ||
     705        1399 :                                 nBottomBorder < pEndRow->nBottomBorder
     706             :                             )
     707             :                     {
     708         489 :                         pEndRow->nBottomBorder = nBottomBorder;
     709             :                     }
     710             :                 }
     711             :             }
     712             :             else
     713             :             {
     714             :                 FillTableRowsCols( nOldRPos, nOldRow, nOldCPos, nOldCol,
     715             :                                     nRPos-nOldRPos, nCPos-nOldCPos,
     716           0 :                                     pBox->GetTabLines(),
     717             :                                     pLineBrush, nDepth-1,
     718           0 :                                     nNumOfHeaderRows );
     719           0 :                 bSubExpanded = sal_True;
     720             :             }
     721             : 
     722        1832 :             nCol++; // The next cell begins in the next column
     723             :         }
     724             : 
     725         623 :         nRow++;
     726         623 :     }
     727         113 : }
     728             : 
     729         113 : SwWriteTable::SwWriteTable(const SwTableLines& rLines, long nWidth,
     730             :     sal_uInt32 nBWidth, bool bRel, sal_uInt16 nMaxDepth, sal_uInt16 nLSub, sal_uInt16 nRSub, sal_uInt32 nNumOfRowsToRepeat)
     731             :     : 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         113 :     bCollectBorderWidth(true)
     740             : {
     741         113 :     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         113 :     SwWriteTableCol *pCol = new SwWriteTableCol( nParentWidth );
     746         113 :     aCols.insert( pCol );
     747         113 :     bUseLayoutHeights = true;
     748         113 :     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         113 :     bUseLayoutHeights = true;
     755             :     // And now fill with life
     756         113 :     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         113 :     if( !nBorder )
     760          36 :         nBorder = nInnerBorder;
     761         113 : }
     762             : 
     763           0 : SwWriteTable::SwWriteTable( const SwHTMLTableLayout *pLayoutInfo )
     764             :     : nBorderColor((sal_uInt32)-1), nCellSpacing(0), nCellPadding(0), nBorder(0),
     765           0 :     nInnerBorder(0), nBaseWidth(pLayoutInfo->GetWidthOption()), nHeadEndRow(0),
     766           0 :     nLeftSub(0), nRightSub(0), nTabWidth(pLayoutInfo->GetWidthOption()),
     767           0 :     bRelWidths(pLayoutInfo->HasPrcWidthOption()), bUseLayoutHeights(false),
     768             : #ifdef DBG_UTIL
     769             :     m_bGetLineHeightCalled(false),
     770             : #endif
     771           0 :     bColsOption(pLayoutInfo->HasColsOption()),
     772           0 :     bColTags(pLayoutInfo->HasColTags()), bLayoutExport(true),
     773           0 :     bCollectBorderWidth(pLayoutInfo->HaveBordersChanged())
     774             : {
     775           0 :     if( !bCollectBorderWidth )
     776             :     {
     777           0 :         nBorder = pLayoutInfo->GetBorder();
     778           0 :         nCellPadding = pLayoutInfo->GetCellPadding();
     779           0 :         nCellSpacing = pLayoutInfo->GetCellSpacing();
     780             :     }
     781             : 
     782             :     sal_uInt16 nRow, nCol;
     783           0 :     sal_uInt16 nCols = pLayoutInfo->GetColCount();
     784           0 :     sal_uInt16 nRows = pLayoutInfo->GetRowCount();
     785             : 
     786             :     // First set the table structure.
     787           0 :     for( nCol=0; nCol<nCols; nCol++ )
     788             :     {
     789             :         SwWriteTableCol *pCol =
     790           0 :             new SwWriteTableCol( (nCol+1)*COL_DFLT_WIDTH );
     791             : 
     792           0 :         if( bColTags )
     793             :         {
     794             :             const SwHTMLTableLayoutColumn *pLayoutCol =
     795           0 :                 pLayoutInfo->GetColumn( nCol );
     796           0 :             pCol->SetWidthOpt( pLayoutCol->GetWidthOption(),
     797           0 :                                pLayoutCol->IsRelWidthOption() );
     798             :         }
     799             : 
     800           0 :         aCols.insert( pCol );
     801             :     }
     802             : 
     803           0 :     for( nRow=0; nRow<nRows; nRow++ )
     804             :     {
     805             :         SwWriteTableRow *pRow =
     806           0 :             new SwWriteTableRow( (nRow+1)*ROW_DFLT_HEIGHT, bUseLayoutHeights );
     807           0 :         pRow->nTopBorder = 0;
     808           0 :         pRow->nBottomBorder = 0;
     809           0 :         aRows.insert( pRow );
     810             :     }
     811             : 
     812             :     // And now fill with life
     813           0 :     for( nRow=0; nRow<nRows; nRow++ )
     814             :     {
     815           0 :         SwWriteTableRow *pRow = aRows[nRow];
     816             : 
     817           0 :         sal_Bool bHeightExported = sal_False;
     818           0 :         for( nCol=0; nCol<nCols; nCol++ )
     819             :         {
     820             :             const SwHTMLTableLayoutCell *pLayoutCell =
     821           0 :                 pLayoutInfo->GetCell( nRow, nCol );
     822             : 
     823             :             const SwHTMLTableLayoutCnts *pLayoutCnts =
     824           0 :                 pLayoutCell->GetContents();
     825             : 
     826             :             // The cell begins actually a row above or further forward?
     827           0 :             if( ( nRow>0 && pLayoutCnts == pLayoutInfo->GetCell(nRow-1,nCol)
     828           0 :                                                       ->GetContents() ) ||
     829           0 :                 ( nCol>0 && pLayoutCnts == pLayoutInfo->GetCell(nRow,nCol-1)
     830           0 :                                                       ->GetContents() ) )
     831             :             {
     832           0 :                 continue;
     833             :             }
     834             : 
     835           0 :             sal_uInt16 nRowSpan = pLayoutCell->GetRowSpan();
     836           0 :             sal_uInt16 nColSpan = pLayoutCell->GetColSpan();
     837           0 :             const SwTableBox *pBox = pLayoutCnts->GetTableBox();
     838             :             OSL_ENSURE( pBox,
     839             :                     "Table in Table can not be exported over layout" );
     840             : 
     841           0 :             long nHeight = bHeightExported ? 0 : GetLineHeight( pBox );
     842           0 :             const SvxBrushItem *pBrushItem = GetLineBrush( pBox, pRow );
     843             : 
     844             :             SwWriteTableCell *pCell =
     845             :                 pRow->AddCell( pBox, nRow, nCol, nRowSpan, nColSpan,
     846           0 :                                nHeight, pBrushItem );
     847           0 :             pCell->SetWidthOpt( pLayoutCell->GetWidthOption(),
     848           0 :                                 pLayoutCell->IsPrcWidthOption() );
     849             : 
     850           0 :             sal_uInt16 nTopBorder = USHRT_MAX, nBottomBorder = USHRT_MAX;
     851             :             sal_uInt16 nBorderMask =
     852             :             MergeBoxBorders( pBox, nRow, nCol, nRowSpan, nColSpan,
     853           0 :                                 nTopBorder, nBottomBorder );
     854             : 
     855           0 :             SwWriteTableCol *pCol = aCols[nCol];
     856           0 :             if( !(nBorderMask & 4) )
     857           0 :                 pCol->bLeftBorder = false;
     858             : 
     859           0 :             pCol = aCols[nCol+nColSpan-1];
     860           0 :             if( !(nBorderMask & 8) )
     861           0 :                 pCol->bRightBorder = false;
     862             : 
     863           0 :             if( !(nBorderMask & 1) )
     864           0 :                 pRow->bTopBorder = false;
     865             : 
     866           0 :             SwWriteTableRow *pEndRow = aRows[nRow+nRowSpan-1];
     867           0 :             if( !(nBorderMask & 2) )
     868           0 :                 pEndRow->bBottomBorder = false;
     869             : 
     870             :             // The height requires only to be written once
     871           0 :             if( nHeight )
     872           0 :                 bHeightExported = sal_True;
     873             :         }
     874             :     }
     875             : 
     876             :     // Adjust some Twip values to pixel boundaries
     877           0 :     if( bCollectBorderWidth && !nBorder )
     878           0 :         nBorder = nInnerBorder;
     879           0 : }
     880             : 
     881         209 : SwWriteTable::~SwWriteTable()
     882             : {
     883         209 : }
     884             : 
     885             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10