LCOV - code coverage report
Current view: top level - libreoffice/sw/source/filter/writer - wrtswtbl.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 193 385 50.1 %
Date: 2012-12-27 Functions: 14 24 58.3 %
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/brshitem.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             : //-----------------------------------------------------------------------
      36             : 
      37          38 : sal_Int16 SwWriteTableCell::GetVertOri() const
      38             : {
      39          38 :     sal_Int16 eCellVertOri = text::VertOrientation::TOP;
      40          38 :     if( pBox->GetSttNd() )
      41             :     {
      42          38 :         const SfxItemSet& rItemSet = pBox->GetFrmFmt()->GetAttrSet();
      43             :         const SfxPoolItem *pItem;
      44          38 :         if( SFX_ITEM_SET == rItemSet.GetItemState( RES_VERT_ORIENT, sal_False, &pItem ) )
      45             :         {
      46             :             sal_Int16 eBoxVertOri =
      47           0 :                 ((const SwFmtVertOrient *)pItem)->GetVertOrient();
      48           0 :             if( text::VertOrientation::CENTER==eBoxVertOri || text::VertOrientation::BOTTOM==eBoxVertOri)
      49           0 :                 eCellVertOri = eBoxVertOri;
      50             :         }
      51             :     }
      52             : 
      53          38 :     return eCellVertOri;
      54             : }
      55             : 
      56             : //-----------------------------------------------------------------------
      57             : 
      58          24 : SwWriteTableRow::SwWriteTableRow( long nPosition, sal_Bool bUseLayoutHeights )
      59             :     : pBackground(0), nPos(nPosition), mbUseLayoutHeights(bUseLayoutHeights),
      60             :     nTopBorder(USHRT_MAX), nBottomBorder(USHRT_MAX), bTopBorder(true),
      61          24 :     bBottomBorder(true)
      62             : {
      63          24 : }
      64             : 
      65          38 : SwWriteTableCell *SwWriteTableRow::AddCell( const SwTableBox *pBox,
      66             :                                 sal_uInt16 nRow, sal_uInt16 nCol,
      67             :                                 sal_uInt16 nRowSpan, sal_uInt16 nColSpan,
      68             :                                 long nHeight,
      69             :                                 const SvxBrushItem *pBackgroundBrush )
      70             : {
      71             :     SwWriteTableCell *pCell =
      72             :         new SwWriteTableCell( pBox, nRow, nCol, nRowSpan, nColSpan,
      73          38 :                                 nHeight, pBackgroundBrush );
      74          38 :     aCells.push_back( pCell );
      75             : 
      76          38 :     return pCell;
      77             : }
      78             : 
      79             : //-----------------------------------------------------------------------
      80             : 
      81          69 : SwWriteTableCol::SwWriteTableCol(sal_uInt32 nPosition)
      82             :     : nPos(nPosition), nWidthOpt(0), bRelWidthOpt(false), bOutWidth(true),
      83          69 :     bLeftBorder(true), bRightBorder(true)
      84             : {
      85          69 : }
      86             : 
      87             : //-----------------------------------------------------------------------
      88             : 
      89          52 : sal_uInt32 SwWriteTable::GetBoxWidth( const SwTableBox *pBox )
      90             : {
      91          52 :     const SwFrmFmt *pFmt = pBox->GetFrmFmt();
      92             :     const SwFmtFrmSize& aFrmSize=
      93          52 :         (const SwFmtFrmSize&)pFmt->GetFmtAttr( RES_FRM_SIZE );
      94             : 
      95          52 :     return sal::static_int_cast<sal_uInt32>(aFrmSize.GetSize().Width());
      96             : }
      97             : 
      98          24 : long SwWriteTable::GetLineHeight( const SwTableLine *pLine )
      99             : {
     100             : #ifdef DBG_UTIL
     101             :     sal_Bool bOldGetLineHeightCalled = m_bGetLineHeightCalled;
     102             :     m_bGetLineHeightCalled = sal_True;
     103             : #endif
     104             : 
     105          24 :     long nHeight = 0;
     106          24 :     if( bUseLayoutHeights )
     107             :     {
     108             :         // Erstmal versuchen wir die Hoehe ueber das Layout zu bekommen
     109          24 :         bool bLayoutAvailable = false;
     110          24 :         nHeight = pLine->GetTableLineHeight(bLayoutAvailable);
     111          24 :         if( nHeight > 0 )
     112          24 :             return nHeight;
     113             : 
     114             :         // Wenn kein Layout gefunden wurde, gehen wir von festen Hoehen aus.
     115             :         // #i60390# - in some cases we still want to continue
     116             :         // to use the layout heights even if one of the rows has a height of 0
     117             :         // ('hidden' rows)
     118           0 :         bUseLayoutHeights = bLayoutAvailable; /*sal_False;*/
     119             : 
     120             : #ifdef DBG_UTIL
     121             :         SAL_WARN_IF( !bLayoutAvailable && bOldGetLineHeightCalled, "sw", "Layout ungueltig?" );
     122             : #endif
     123             :     }
     124             : 
     125           0 :     const SwTableBoxes& rBoxes = pLine->GetTabBoxes();
     126           0 :     sal_uInt16 nBoxes = rBoxes.size();
     127             : 
     128           0 :     for( sal_uInt16 nBox=0; nBox<nBoxes; nBox++ )
     129             :     {
     130           0 :         const SwTableBox* pBox = rBoxes[nBox];
     131           0 :         if( pBox->GetSttNd() )
     132             :         {
     133           0 :             if( nHeight < ROW_DFLT_HEIGHT )
     134           0 :                 nHeight = ROW_DFLT_HEIGHT;
     135             :         }
     136             :         else
     137             :         {
     138           0 :             long nTmp = 0;
     139           0 :             const SwTableLines &rLines = pBox->GetTabLines();
     140           0 :             for( sal_uInt16 nLine=0; nLine<rLines.size(); nLine++ )
     141             :             {
     142           0 :                 nTmp += GetLineHeight( rLines[nLine] );
     143             :             }
     144           0 :             if( nHeight < nTmp )
     145           0 :                 nHeight = nTmp;
     146             :         }
     147             :     }
     148             : 
     149           0 :     return nHeight;
     150             : }
     151             : 
     152           0 : long SwWriteTable::GetLineHeight( const SwTableBox *pBox ) const
     153             : {
     154           0 :     const SwTableLine *pLine = pBox->GetUpper();
     155             : 
     156           0 :     if( !pLine )
     157           0 :         return 0;
     158             : 
     159           0 :     const SwFrmFmt *pLineFrmFmt = pLine->GetFrmFmt();
     160             :     const SfxPoolItem* pItem;
     161           0 :     const SfxItemSet& rItemSet = pLineFrmFmt->GetAttrSet();
     162             : 
     163           0 :     long nHeight = 0;
     164           0 :     if( SFX_ITEM_SET == rItemSet.GetItemState( RES_FRM_SIZE, sal_True, &pItem ))
     165           0 :         nHeight = ((SwFmtFrmSize*)pItem)->GetHeight();
     166             : 
     167           0 :     return nHeight;
     168             : }
     169             : 
     170           0 : const SvxBrushItem *SwWriteTable::GetLineBrush( const SwTableBox *pBox,
     171             :                                                   SwWriteTableRow *pRow )
     172             : {
     173           0 :     const SwTableLine *pLine = pBox->GetUpper();
     174             : 
     175           0 :     while( pLine )
     176             :     {
     177           0 :         const SwFrmFmt *pLineFrmFmt = pLine->GetFrmFmt();
     178             :         const SfxPoolItem* pItem;
     179           0 :         const SfxItemSet& rItemSet = pLineFrmFmt->GetAttrSet();
     180             : 
     181           0 :         if( SFX_ITEM_SET == rItemSet.GetItemState( RES_BACKGROUND, sal_False,
     182           0 :                                                    &pItem ) )
     183             :         {
     184           0 :             if( !pLine->GetUpper() )
     185             :             {
     186           0 :                 if( !pRow->GetBackground() )
     187           0 :                     pRow->SetBackground( (const SvxBrushItem *)pItem );
     188           0 :                 pItem = 0;
     189             :             }
     190             : 
     191           0 :             return (const SvxBrushItem *)pItem;
     192             :         }
     193             : 
     194           0 :         pBox = pLine->GetUpper();
     195           0 :         pLine = pBox ? pBox->GetUpper() : 0;
     196             :     }
     197             : 
     198           0 :     return 0;
     199             : }
     200             : 
     201             : 
     202          72 : void SwWriteTable::MergeBorders( const SvxBorderLine* pBorderLine,
     203             :                                    bool bTable )
     204             : {
     205          72 :     if( (sal_uInt32)-1 == nBorderColor )
     206             :     {
     207           2 :         Color aGrayColor( COL_GRAY );
     208           2 :         if( !pBorderLine->GetColor().IsRGBEqual( aGrayColor ) )
     209           2 :             nBorderColor = pBorderLine->GetColor().GetColor();
     210             :     }
     211             : 
     212          72 :     if( !bCollectBorderWidth )
     213          72 :         return;
     214             : 
     215          72 :     sal_uInt16 nOutWidth = pBorderLine->GetOutWidth();
     216          72 :     if( bTable )
     217             :     {
     218          26 :         if( nOutWidth && (!nBorder || nOutWidth < nBorder) )
     219           2 :             nBorder = nOutWidth;
     220             :     }
     221             :     else
     222             :     {
     223          46 :         if( nOutWidth && (!nInnerBorder || nOutWidth < nInnerBorder) )
     224           3 :             nInnerBorder = nOutWidth;
     225             :     }
     226             : 
     227          72 :     sal_uInt16 nDist = pBorderLine->GetInWidth() ? pBorderLine->GetDistance()
     228          72 :                                                 : 0;
     229          72 :     if( nDist && (!nCellSpacing || nDist < nCellSpacing) )
     230           0 :         nCellSpacing = nDist;
     231             : }
     232             : 
     233             : 
     234          38 : sal_uInt16 SwWriteTable::MergeBoxBorders( const SwTableBox *pBox,
     235             :                                         size_t const nRow, size_t const nCol,
     236             :                                         sal_uInt16 nRowSpan, sal_uInt16 nColSpan,
     237             :                                         sal_uInt16& rTopBorder,
     238             :                                         sal_uInt16 &rBottomBorder )
     239             : {
     240          38 :     sal_uInt16 nBorderMask = 0;
     241             : 
     242          38 :     const SwFrmFmt *pFrmFmt = pBox->GetFrmFmt();
     243          38 :     const SvxBoxItem& rBoxItem = (const SvxBoxItem&)pFrmFmt->GetFmtAttr( RES_BOX );
     244             : 
     245          38 :     if( rBoxItem.GetTop() )
     246             :     {
     247          18 :         nBorderMask |= 1;
     248          18 :         MergeBorders( rBoxItem.GetTop(), nRow==0 );
     249          18 :         rTopBorder = rBoxItem.GetTop()->GetOutWidth();
     250             :     }
     251             : 
     252          38 :     if( rBoxItem.GetLeft() )
     253             :     {
     254          18 :         nBorderMask |= 4;
     255          18 :         MergeBorders( rBoxItem.GetLeft(), nCol==0 );
     256             :     }
     257             : 
     258          38 :     if( rBoxItem.GetBottom() )
     259             :     {
     260          18 :         nBorderMask |= 2;
     261          18 :         MergeBorders( rBoxItem.GetBottom(), nRow+nRowSpan==aRows.size() );
     262          18 :         rBottomBorder = rBoxItem.GetBottom()->GetOutWidth();
     263             :     }
     264             : 
     265          38 :     if( rBoxItem.GetRight() )
     266             :     {
     267          18 :         nBorderMask |= 8;
     268          18 :         MergeBorders( rBoxItem.GetRight(), nCol+nColSpan==aCols.size() );
     269             :     }
     270             : 
     271             :     // If any distance is set, the smallest one is used. This holds for
     272             :     // the four distance of a box as well as for the distances of different
     273             :     // boxes.
     274          38 :     if( bCollectBorderWidth )
     275             :     {
     276          38 :         sal_uInt16 nDist = rBoxItem.GetDistance( BOX_LINE_TOP );
     277          38 :         if( nDist && (!nCellPadding || nDist < nCellPadding) )
     278           0 :             nCellPadding = nDist;
     279          38 :         nDist = rBoxItem.GetDistance( BOX_LINE_BOTTOM );
     280          38 :         if( nDist && (!nCellPadding || nDist < nCellPadding) )
     281           0 :             nCellPadding = nDist;
     282          38 :         nDist = rBoxItem.GetDistance( BOX_LINE_LEFT );
     283          38 :         if( nDist && (!nCellPadding || nDist < nCellPadding) )
     284           4 :             nCellPadding = nDist;
     285          38 :         nDist = rBoxItem.GetDistance( BOX_LINE_RIGHT );
     286          38 :         if( nDist && (!nCellPadding || nDist < nCellPadding) )
     287           3 :             nCellPadding = nDist;
     288             :     }
     289             : 
     290          38 :     return nBorderMask;
     291             : }
     292             : 
     293             : 
     294           0 : sal_uInt32  SwWriteTable::GetRawWidth( sal_uInt16 nCol, sal_uInt16 nColSpan ) const
     295             : {
     296           0 :     sal_uInt32 nWidth = aCols[nCol+nColSpan-1]->GetPos();
     297           0 :     if( nCol > 0 )
     298           0 :         nWidth = nWidth - aCols[nCol-1]->GetPos();
     299             : 
     300           0 :     return nWidth;
     301             : }
     302             : 
     303           0 : sal_uInt16 SwWriteTable::GetLeftSpace( sal_uInt16 nCol ) const
     304             : {
     305           0 :     sal_uInt16 nSpace = nCellPadding + nCellSpacing;
     306             : 
     307             :     // In der ersten Spalte auch noch die Liniendicke abziehen
     308           0 :     if( nCol==0 )
     309             :     {
     310           0 :         nSpace = nSpace + nLeftSub;
     311             : 
     312           0 :         const SwWriteTableCol *pCol = aCols[nCol];
     313           0 :         if( pCol->HasLeftBorder() )
     314           0 :             nSpace = nSpace + nBorder;
     315             :     }
     316             : 
     317           0 :     return nSpace;
     318             : }
     319             : 
     320             : sal_uInt16
     321           0 : SwWriteTable::GetRightSpace(size_t const nCol, sal_uInt16 nColSpan) const
     322             : {
     323           0 :     sal_uInt16 nSpace = nCellPadding;
     324             : 
     325             :     // In der letzten Spalte noch einmal zusaetzlich CELLSPACING und
     326             :     // und die Liniendicke abziehen
     327           0 :     if( nCol+nColSpan==aCols.size() )
     328             :     {
     329           0 :         nSpace += (nCellSpacing + nRightSub);
     330             : 
     331           0 :         const SwWriteTableCol *pCol = aCols[nCol+nColSpan-1];
     332           0 :         if( pCol->HasRightBorder() )
     333           0 :             nSpace = nSpace + nBorder;
     334             :     }
     335             : 
     336           0 :     return nSpace;
     337             : }
     338             : 
     339           0 : sal_uInt16 SwWriteTable::GetAbsWidth( sal_uInt16 nCol, sal_uInt16 nColSpan ) const
     340             : {
     341           0 :     sal_uInt32 nWidth = GetRawWidth( nCol, nColSpan );
     342           0 :     if( nBaseWidth != nTabWidth )
     343             :     {
     344           0 :         nWidth *= nTabWidth;
     345           0 :         nWidth /= nBaseWidth;
     346             :     }
     347             : 
     348           0 :     nWidth -= GetLeftSpace( nCol ) + GetRightSpace( nCol, nColSpan );
     349             : 
     350             :     OSL_ENSURE( nWidth > 0, "Spaltenbreite <= 0. OK?" );
     351           0 :     return nWidth > 0 ? (sal_uInt16)nWidth : 0;
     352             : }
     353             : 
     354           0 : sal_uInt16 SwWriteTable::GetRelWidth( sal_uInt16 nCol, sal_uInt16 nColSpan ) const
     355             : {
     356           0 :     long nWidth = GetRawWidth( nCol, nColSpan );
     357             : 
     358           0 :     return (sal_uInt16)(long)Fraction( nWidth*256 + GetBaseWidth()/2,
     359           0 :                                    GetBaseWidth() );
     360             : }
     361             : 
     362           0 : sal_uInt16 SwWriteTable::GetPrcWidth( sal_uInt16 nCol, sal_uInt16 nColSpan ) const
     363             : {
     364           0 :     long nWidth = GetRawWidth( nCol, nColSpan );
     365             : 
     366             :     // sieht komisch aus, ist aber nichts anderes als
     367             :     //  [(100 * nWidth) + .5] ohne Rundungsfehler
     368           0 :     return (sal_uInt16)(long)Fraction( nWidth*100 + GetBaseWidth()/2,
     369           0 :                                    GetBaseWidth() );
     370             : }
     371             : 
     372           0 : long SwWriteTable::GetAbsHeight(long nRawHeight, size_t const nRow,
     373             :                                    sal_uInt16 nRowSpan ) const
     374             : {
     375           0 :     nRawHeight -= (2*nCellPadding + nCellSpacing);
     376             : 
     377             :     // In der ersten Zeile noch einmal zusaetzlich CELLSPACING und
     378             :     // und die Liniendicke abziehen
     379           0 :     const SwWriteTableRow *pRow = 0;
     380           0 :     if( nRow==0 )
     381             :     {
     382           0 :         nRawHeight -= nCellSpacing;
     383           0 :         pRow = aRows[nRow];
     384           0 :         if( pRow->HasTopBorder() )
     385           0 :             nRawHeight -= nBorder;
     386             :     }
     387             : 
     388             :     // In der letzten Zeile noch die Liniendicke abziehen
     389           0 :     if( nRow+nRowSpan==aRows.size() )
     390             :     {
     391           0 :         if( !pRow || nRowSpan > 1 )
     392           0 :             pRow = aRows[nRow+nRowSpan-1];
     393           0 :         if( pRow->HasBottomBorder() )
     394           0 :             nRawHeight -= nBorder;
     395             :     }
     396             : 
     397             :     OSL_ENSURE( nRawHeight > 0, "Zeilenheohe <= 0. OK?" );
     398           0 :     return nRawHeight > 0 ? nRawHeight : 0;
     399             : }
     400             : 
     401          76 : sal_Bool SwWriteTable::ShouldExpandSub(const SwTableBox *pBox, sal_Bool /*bExpandedBefore*/,
     402             :     sal_uInt16 nDepth) const
     403             : {
     404          76 :     return !pBox->GetSttNd() && nDepth > 0;
     405             : }
     406             : 
     407           5 : void SwWriteTable::CollectTableRowsCols( long nStartRPos,
     408             :                                            sal_uInt32 nStartCPos,
     409             :                                            long nParentLineHeight,
     410             :                                            sal_uInt32 nParentLineWidth,
     411             :                                            const SwTableLines& rLines,
     412             :                                            sal_uInt16 nDepth )
     413             : {
     414           5 :     sal_Bool bSubExpanded = sal_False;
     415           5 :     sal_uInt16 nLines = rLines.size();
     416             : 
     417             : #if OSL_DEBUG_LEVEL > 0
     418             :     sal_uInt32 nEndCPos = 0;
     419             : #endif
     420             : 
     421           5 :     long nRPos = nStartRPos;
     422          17 :     for( sal_uInt16 nLine = 0; nLine < nLines; nLine++ )
     423             :     {
     424          12 :         /*const*/ SwTableLine *pLine = rLines[nLine];
     425             : 
     426          12 :         long nOldRPos = nRPos;
     427             : 
     428          12 :         if( nLine < nLines-1 || nParentLineHeight==0  )
     429             :         {
     430          12 :             long nLineHeight = GetLineHeight( pLine );
     431          12 :             nRPos += nLineHeight;
     432          12 :             if( nParentLineHeight && nStartRPos + nParentLineHeight <= nRPos )
     433             :             {
     434             :                 /* If you have corrupt line height information, e.g. breaking rows in complex table
     435             :                 layout, you may run into this robust code.
     436             :                 It's not allowed that subrows leaves their parentrow. If this would happen the line
     437             :                 height of subrow is reduced to a part of the remaining height */
     438             :                 OSL_FAIL( "Corrupt line height I" );
     439           0 :                 nRPos -= nLineHeight;
     440           0 :                 nLineHeight = nStartRPos + nParentLineHeight - nRPos; // remaining parent height
     441           0 :                 nLineHeight /= nLines - nLine; // divided through the number of remaining sub rows
     442           0 :                 nRPos += nLineHeight;
     443             :             }
     444          12 :             SwWriteTableRow *pRow = new SwWriteTableRow( nRPos, bUseLayoutHeights);
     445          12 :             if( !aRows.insert( pRow ).second )
     446           0 :                 delete pRow;
     447             :         }
     448             :         else
     449             :         {
     450             : #if OSL_DEBUG_LEVEL > 0
     451             :             long nCheckPos = nRPos + GetLineHeight( pLine );
     452             : #endif
     453           0 :             nRPos = nStartRPos + nParentLineHeight;
     454             : #if OSL_DEBUG_LEVEL > 0
     455             :             SwWriteTableRow aSrchRow( nRPos, bUseLayoutHeights );
     456             :             OSL_ENSURE( aRows.find( &aSrchRow ) != aRows.end(), "Parent-Zeile nicht gefunden" );
     457             :             SwWriteTableRow aRowCheckPos(nCheckPos,bUseLayoutHeights);
     458             :             SwWriteTableRow aRowRPos(nRPos,bUseLayoutHeights);
     459             :             OSL_ENSURE( !bUseLayoutHeights ||
     460             :                     aRowCheckPos == aRowRPos,
     461             :                     "Hoehe der Zeilen stimmt nicht mit Parent ueberein" );
     462             : #endif
     463             :         }
     464             : 
     465             :         // Fuer alle Boxen der Zeile ggf. eine Spalte einfuegen
     466          12 :         const SwTableBoxes& rBoxes = pLine->GetTabBoxes();
     467          12 :         sal_uInt16 nBoxes = rBoxes.size();
     468             : 
     469          12 :         sal_uInt32 nCPos = nStartCPos;
     470          50 :         for( sal_uInt16 nBox=0; nBox<nBoxes; nBox++ )
     471             :         {
     472          38 :             const SwTableBox *pBox = rBoxes[nBox];
     473             : 
     474          38 :             sal_uInt32 nOldCPos = nCPos;
     475             : 
     476          38 :             if( nBox < nBoxes-1 || (nParentLineWidth==0 && nLine==0)  )
     477             :             {
     478          26 :                 nCPos = nCPos + GetBoxWidth( pBox );
     479          26 :                 SwWriteTableCol *pCol = new SwWriteTableCol( nCPos );
     480             : 
     481          26 :                 if( !aCols.insert( pCol ).second )
     482          15 :                     delete pCol;
     483             : 
     484          26 :                 if( nBox==nBoxes-1 )
     485             :                 {
     486             :                     OSL_ENSURE( nLine==0 && nParentLineWidth==0,
     487             :                             "Jetzt wird die Parent-Breite plattgemacht!" );
     488           0 :                     nParentLineWidth = nCPos-nStartCPos;
     489          26 :                 }
     490             :             }
     491             :             else
     492             :             {
     493             : #if OSL_DEBUG_LEVEL > 0
     494             :                 sal_uInt32 nCheckPos = nCPos + GetBoxWidth( pBox );
     495             :                 if( !nEndCPos )
     496             :                 {
     497             :                     nEndCPos = nCheckPos;
     498             :                 }
     499             :                 else
     500             :                 {
     501             :                     OSL_ENSURE( SwWriteTableCol(nCheckPos) ==
     502             :                                                 SwWriteTableCol(nEndCPos),
     503             :                     "Zelle enthaelt unterschiedlich breite Zeilen" );
     504             :                 }
     505             : #endif
     506          12 :                 nCPos = nStartCPos + nParentLineWidth;
     507             : 
     508             : #if OSL_DEBUG_LEVEL > 0
     509             :                 SwWriteTableCol aSrchCol( nCPos );
     510             :                 OSL_ENSURE( aCols.find( &aSrchCol ) != aCols.end(),
     511             :                         "Parent-Zelle nicht gefunden" );
     512             :                 OSL_ENSURE( SwWriteTableCol(nCheckPos) ==
     513             :                                             SwWriteTableCol(nCPos),
     514             :                         "Breite der Zellen stimmt nicht mit Parent ueberein" );
     515             : #endif
     516             :             }
     517             : 
     518          38 :             if( ShouldExpandSub( pBox, bSubExpanded, nDepth ) )
     519             :             {
     520             :                 CollectTableRowsCols( nOldRPos, nOldCPos,
     521             :                                         nRPos - nOldRPos,
     522             :                                         nCPos - nOldCPos,
     523           0 :                                         pBox->GetTabLines(),
     524           0 :                                         nDepth-1 );
     525           0 :                 bSubExpanded = sal_True;
     526             :             }
     527             :         }
     528             :     }
     529           5 : }
     530             : 
     531             : 
     532           5 : void SwWriteTable::FillTableRowsCols( long nStartRPos, sal_uInt16 nStartRow,
     533             :                                         sal_uInt32 nStartCPos, sal_uInt16 nStartCol,
     534             :                                         long nParentLineHeight,
     535             :                                         sal_uInt32 nParentLineWidth,
     536             :                                         const SwTableLines& rLines,
     537             :                                         const SvxBrushItem* pParentBrush,
     538             :                                         sal_uInt16 nDepth,
     539             :                                         sal_uInt16 nNumOfHeaderRows )
     540             : {
     541           5 :     sal_uInt16 nLines = rLines.size();
     542           5 :     sal_Bool bSubExpanded = sal_False;
     543             : 
     544             :     // Festlegen der Umrandung
     545           5 :     long nRPos = nStartRPos;
     546           5 :     sal_uInt16 nRow = nStartRow;
     547             : 
     548          17 :     for( sal_uInt16 nLine = 0; nLine < nLines; nLine++ )
     549             :     {
     550          12 :         const SwTableLine *pLine = rLines[nLine];
     551             : 
     552             :         // Position der letzten ueberdeckten Zeile ermitteln
     553          12 :         long nOldRPos = nRPos;
     554          12 :         if( nLine < nLines-1 || nParentLineHeight==0 )
     555             :         {
     556          12 :             long nLineHeight = GetLineHeight( pLine );
     557          12 :             nRPos += nLineHeight;
     558          12 :             if( nParentLineHeight && nStartRPos + nParentLineHeight <= nRPos )
     559             :             {
     560             :                 /* See comment in CollectTableRowCols */
     561             :                 OSL_FAIL( "Corrupt line height II" );
     562           0 :                 nRPos -= nLineHeight;
     563           0 :                 nLineHeight = nStartRPos + nParentLineHeight - nRPos; // remaining parent height
     564           0 :                 nLineHeight /= nLines - nLine; // divided through the number of remaining sub rows
     565           0 :                 nRPos += nLineHeight;
     566          12 :             }
     567             :         }
     568             :         else
     569           0 :             nRPos = nStartRPos + nParentLineHeight;
     570             : 
     571             :         // Und ihren Index
     572          12 :         sal_uInt16 nOldRow = nRow;
     573          12 :         SwWriteTableRow aSrchRow( nRPos,bUseLayoutHeights );
     574          12 :         SwWriteTableRows::const_iterator it2 = aRows.find( &aSrchRow );
     575             :         OSL_ENSURE( it2 != aRows.end(), "missing row" );
     576          12 :         nRow = it2 - aRows.begin();
     577             : 
     578             :         OSL_ENSURE( nOldRow <= nRow, "Don't look back!" );
     579          12 :         if( nOldRow > nRow )
     580             :         {
     581           0 :             nOldRow = nRow;
     582           0 :             if( nOldRow )
     583           0 :                 --nOldRow;
     584             :         }
     585             : 
     586             : 
     587          12 :         SwWriteTableRow *pRow = aRows[nOldRow];
     588          12 :         SwWriteTableRow *pEndRow = aRows[nRow];
     589          12 :         if( nLine+1==nNumOfHeaderRows && nParentLineHeight==0 )
     590           0 :             nHeadEndRow = nRow;
     591             : 
     592          12 :         const SwTableBoxes& rBoxes = pLine->GetTabBoxes();
     593             : 
     594          12 :         const SwFrmFmt *pLineFrmFmt = pLine->GetFrmFmt();
     595             :         const SfxPoolItem* pItem;
     596          12 :         const SfxItemSet& rItemSet = pLineFrmFmt->GetAttrSet();
     597             : 
     598          12 :         long nHeight = 0;
     599          12 :         if( SFX_ITEM_SET == rItemSet.GetItemState( RES_FRM_SIZE, sal_True, &pItem ))
     600           0 :             nHeight = ((SwFmtFrmSize*)pItem)->GetHeight();
     601             : 
     602             : 
     603          12 :         const SvxBrushItem *pBrushItem, *pLineBrush = pParentBrush;
     604          12 :         if( SFX_ITEM_SET == rItemSet.GetItemState( RES_BACKGROUND, sal_False,
     605          12 :                                                    &pItem ) )
     606             :         {
     607           0 :             pLineBrush = (const SvxBrushItem *)pItem;
     608             : 
     609             :             // Wenn die Zeile die gesamte Tabelle umspannt, koennen
     610             :             // Wir den Hintergrund an der Zeile ausgeben. Sonst muessen
     611             :             // wir in an den Zelle ausgeben.
     612           0 :             sal_Bool bOutAtRow = !nParentLineWidth;
     613           0 :             if( !bOutAtRow && nStartCPos==0 )
     614             :             {
     615           0 :                 SwWriteTableCol aCol( nParentLineWidth );
     616           0 :                 bOutAtRow = aCols.find( &aCol ) == (aCols.end() - 1);
     617             :             }
     618           0 :             if( bOutAtRow )
     619             :             {
     620           0 :                 pRow->SetBackground( pLineBrush );
     621           0 :                 pBrushItem = 0;
     622             :             }
     623             :             else
     624           0 :                 pBrushItem = pLineBrush;
     625             :         }
     626             :         else
     627             :         {
     628          12 :             pRow->SetBackground( pLineBrush );
     629          12 :             pBrushItem = 0;
     630             :         }
     631             : 
     632          12 :         sal_uInt16 nBoxes = rBoxes.size();
     633          12 :         sal_uInt32 nCPos = nStartCPos;
     634          12 :         sal_uInt16 nCol = nStartCol;
     635             : 
     636          50 :         for( sal_uInt16 nBox=0; nBox<nBoxes; nBox++ )
     637             :         {
     638          38 :             const SwTableBox *pBox = rBoxes[nBox];
     639             : 
     640             :             // Position der letzten ueberdeckten Spalte ermitteln
     641          38 :             sal_uInt32 nOldCPos = nCPos;
     642          38 :             if( nBox < nBoxes-1 || (nParentLineWidth==0 && nLine==0) )
     643             :             {
     644          26 :                 nCPos = nCPos + GetBoxWidth( pBox );
     645          52 :                 if( nBox==nBoxes-1 )
     646           0 :                     nParentLineWidth = nCPos - nStartCPos;
     647             :             }
     648             :             else
     649          12 :                 nCPos = nStartCPos + nParentLineWidth;
     650             : 
     651             :             // Und ihren Index
     652          38 :             sal_uInt16 nOldCol = nCol;
     653          38 :             SwWriteTableCol aSrchCol( nCPos );
     654          38 :             SwWriteTableCols::const_iterator it = aCols.find( &aSrchCol );
     655             :             OSL_ENSURE( it != aCols.end(), "missing column" );
     656          38 :             nCol = it - aCols.begin();
     657             : 
     658          38 :             if( !ShouldExpandSub( pBox, bSubExpanded, nDepth ) )
     659             :             {
     660          38 :                 sal_uInt16 nRowSpan = nRow - nOldRow + 1;
     661             : 
     662             :                 // The new table model may have true row span attributes
     663          38 :                 const long nAttrRowSpan = pBox->getRowSpan();
     664          38 :                 if ( 1 < nAttrRowSpan )
     665           0 :                     nRowSpan = (sal_uInt16)nAttrRowSpan;
     666          38 :                 else if ( nAttrRowSpan < 1 )
     667           0 :                     nRowSpan = 0;
     668             : 
     669          38 :                 sal_uInt16 nColSpan = nCol - nOldCol + 1;
     670             :                 pRow->AddCell( pBox, nOldRow, nOldCol,
     671             :                                nRowSpan, nColSpan, nHeight,
     672          38 :                                pBrushItem );
     673          38 :                 nHeight = 0; // Die Hoehe braucht nur einmal geschieben werden
     674             : 
     675          38 :                 if( pBox->GetSttNd() )
     676             :                 {
     677          38 :                     sal_uInt16 nTopBorder = USHRT_MAX, nBottomBorder = USHRT_MAX;
     678             :                     sal_uInt16 nBorderMask = MergeBoxBorders(pBox, nOldRow, nOldCol,
     679          38 :                         nRowSpan, nColSpan, nTopBorder, nBottomBorder);
     680             : 
     681             :                     // #i30094# add a sanity check here to ensure that
     682             :                     // we don't access an invalid aCols[] as &nCol
     683             :                     // above can be changed.
     684          38 :                     if (!(nBorderMask & 4) && nOldCol < aCols.size())
     685             :                     {
     686          20 :                         SwWriteTableCol *pCol = aCols[nOldCol];
     687             :                         OSL_ENSURE(pCol, "No TableCol found, panic!");
     688          20 :                         if (pCol)
     689          20 :                             pCol->bLeftBorder = false;
     690             :                     }
     691             : 
     692          38 :                     if (!(nBorderMask & 8))
     693             :                     {
     694          20 :                         SwWriteTableCol *pCol = aCols[nCol];
     695             :                         OSL_ENSURE(pCol, "No TableCol found, panic!");
     696          20 :                         if (pCol)
     697          20 :                             pCol->bRightBorder = false;
     698             :                     }
     699             : 
     700          38 :                     if (!(nBorderMask & 1))
     701          20 :                         pRow->bTopBorder = false;
     702          18 :                     else if (!pRow->nTopBorder || nTopBorder < pRow->nTopBorder)
     703           6 :                         pRow->nTopBorder = nTopBorder;
     704             : 
     705          38 :                     if (!(nBorderMask & 2))
     706          20 :                         pEndRow->bBottomBorder = false;
     707          18 :                     else if (
     708          18 :                                 !pEndRow->nBottomBorder ||
     709             :                                 nBottomBorder < pEndRow->nBottomBorder
     710             :                             )
     711             :                     {
     712           6 :                         pEndRow->nBottomBorder = nBottomBorder;
     713             :                     }
     714             :                 }
     715             :             }
     716             :             else
     717             :             {
     718             :                 FillTableRowsCols( nOldRPos, nOldRow, nOldCPos, nOldCol,
     719             :                                     nRPos-nOldRPos, nCPos-nOldCPos,
     720           0 :                                     pBox->GetTabLines(),
     721             :                                     pLineBrush, nDepth-1,
     722           0 :                                     nNumOfHeaderRows );
     723           0 :                 bSubExpanded = sal_True;
     724             :             }
     725             : 
     726          38 :             nCol++; // Die naechste Zelle faengt in der nachten Spalte an
     727             :         }
     728             : 
     729          12 :         nRow++;
     730          12 :     }
     731           5 : }
     732             : 
     733           5 : SwWriteTable::SwWriteTable(const SwTableLines& rLines, long nWidth,
     734             :     sal_uInt32 nBWidth, bool bRel, sal_uInt16 nMaxDepth, sal_uInt16 nLSub, sal_uInt16 nRSub, sal_uInt32 nNumOfRowsToRepeat)
     735             :     : nBorderColor((sal_uInt32)-1), nCellSpacing(0), nCellPadding(0), nBorder(0),
     736             :     nInnerBorder(0), nBaseWidth(nBWidth), nHeadEndRow(USHRT_MAX),
     737             :      nLeftSub(nLSub), nRightSub(nRSub), nTabWidth(nWidth), bRelWidths(bRel),
     738             :     bUseLayoutHeights(true),
     739             : #ifdef DBG_UTIL
     740             :     m_bGetLineHeightCalled(false),
     741             : #endif
     742             :     bColsOption(false), bColTags(true), bLayoutExport(false),
     743           5 :     bCollectBorderWidth(true)
     744             : {
     745           5 :     sal_uInt32 nParentWidth = nBaseWidth + nLeftSub + nRightSub;
     746             : 
     747             :     // Erstmal die Tabellen-Struktur festlegen. Hinter der Tabelle ist in
     748             :     // jedem Fall eine Spalte zu Ende
     749           5 :     SwWriteTableCol *pCol = new SwWriteTableCol( nParentWidth );
     750           5 :     aCols.insert( pCol );
     751           5 :     CollectTableRowsCols( 0, 0, 0, nParentWidth, rLines, nMaxDepth - 1 );
     752             : 
     753             :     // Und jetzt mit leben fuellen
     754           5 :     FillTableRowsCols( 0, 0, 0, 0, 0, nParentWidth, rLines, 0, nMaxDepth - 1, static_cast< sal_uInt16 >(nNumOfRowsToRepeat) );
     755             : 
     756             :     // Einige Twip-Werte an Pixel-Grenzen anpassen
     757           5 :     if( !nBorder )
     758           3 :         nBorder = nInnerBorder;
     759           5 : }
     760             : 
     761           0 : SwWriteTable::SwWriteTable( const SwHTMLTableLayout *pLayoutInfo )
     762             :     : nBorderColor((sal_uInt32)-1), nCellSpacing(0), nCellPadding(0), nBorder(0),
     763           0 :     nInnerBorder(0), nBaseWidth(pLayoutInfo->GetWidthOption()), nHeadEndRow(0),
     764           0 :     nLeftSub(0), nRightSub(0), nTabWidth(pLayoutInfo->GetWidthOption()),
     765           0 :     bRelWidths(pLayoutInfo->HasPrcWidthOption()), bUseLayoutHeights(false),
     766             : #ifdef DBG_UTIL
     767             :     m_bGetLineHeightCalled(false),
     768             : #endif
     769           0 :     bColsOption(pLayoutInfo->HasColsOption()),
     770           0 :     bColTags(pLayoutInfo->HasColTags()), bLayoutExport(true),
     771           0 :     bCollectBorderWidth(pLayoutInfo->HaveBordersChanged())
     772             : {
     773           0 :     if( !bCollectBorderWidth )
     774             :     {
     775           0 :         nBorder = pLayoutInfo->GetBorder();
     776           0 :         nCellPadding = pLayoutInfo->GetCellPadding();
     777           0 :         nCellSpacing = pLayoutInfo->GetCellSpacing();
     778             :     }
     779             : 
     780             :     sal_uInt16 nRow, nCol;
     781           0 :     sal_uInt16 nCols = pLayoutInfo->GetColCount();
     782           0 :     sal_uInt16 nRows = pLayoutInfo->GetRowCount();
     783             : 
     784             :     // Erstmal die Tabellen-Struktur festlegen.
     785           0 :     for( nCol=0; nCol<nCols; nCol++ )
     786             :     {
     787             :         SwWriteTableCol *pCol =
     788           0 :             new SwWriteTableCol( (nCol+1)*COL_DFLT_WIDTH );
     789             : 
     790           0 :         if( bColTags )
     791             :         {
     792             :             const SwHTMLTableLayoutColumn *pLayoutCol =
     793           0 :                 pLayoutInfo->GetColumn( nCol );
     794           0 :             pCol->SetWidthOpt( pLayoutCol->GetWidthOption(),
     795           0 :                                pLayoutCol->IsRelWidthOption() );
     796             :         }
     797             : 
     798           0 :         aCols.insert( pCol );
     799             :     }
     800             : 
     801           0 :     for( nRow=0; nRow<nRows; nRow++ )
     802             :     {
     803             :         SwWriteTableRow *pRow =
     804           0 :             new SwWriteTableRow( (nRow+1)*ROW_DFLT_HEIGHT, bUseLayoutHeights );
     805           0 :         pRow->nTopBorder = 0;
     806           0 :         pRow->nBottomBorder = 0;
     807           0 :         aRows.insert( pRow );
     808             :     }
     809             : 
     810             :     // Und jetzt mit leben fuellen
     811           0 :     for( nRow=0; nRow<nRows; nRow++ )
     812             :     {
     813           0 :         SwWriteTableRow *pRow = aRows[nRow];
     814             : 
     815           0 :         sal_Bool bHeightExported = sal_False;
     816           0 :         for( nCol=0; nCol<nCols; nCol++ )
     817             :         {
     818             :             const SwHTMLTableLayoutCell *pLayoutCell =
     819           0 :                 pLayoutInfo->GetCell( nRow, nCol );
     820             : 
     821             :             const SwHTMLTableLayoutCnts *pLayoutCnts =
     822           0 :                 pLayoutCell->GetContents();
     823             : 
     824             :             // Beginnt die Zelle eigentlich eine Zeile weiter oben oder
     825             :             // weiter vorne?
     826           0 :             if( ( nRow>0 && pLayoutCnts == pLayoutInfo->GetCell(nRow-1,nCol)
     827           0 :                                                       ->GetContents() ) ||
     828             :                 ( nCol>0 && pLayoutCnts == pLayoutInfo->GetCell(nRow,nCol-1)
     829           0 :                                                       ->GetContents() ) )
     830             :             {
     831           0 :                 continue;
     832             :             }
     833             : 
     834           0 :             sal_uInt16 nRowSpan = pLayoutCell->GetRowSpan();
     835           0 :             sal_uInt16 nColSpan = pLayoutCell->GetColSpan();
     836           0 :             const SwTableBox *pBox = pLayoutCnts->GetTableBox();
     837             :             OSL_ENSURE( pBox,
     838             :                     "Tabelle in Tabelle kann nicht ueber Layout exportiert werden" );
     839             : 
     840           0 :             long nHeight = bHeightExported ? 0 : GetLineHeight( pBox );
     841           0 :             const SvxBrushItem *pBrushItem = GetLineBrush( pBox, pRow );
     842             : 
     843             :             SwWriteTableCell *pCell =
     844             :                 pRow->AddCell( pBox, nRow, nCol, nRowSpan, nColSpan,
     845           0 :                                nHeight, pBrushItem );
     846           0 :             pCell->SetWidthOpt( pLayoutCell->GetWidthOption(),
     847           0 :                                 pLayoutCell->IsPrcWidthOption() );
     848             : 
     849           0 :             sal_uInt16 nTopBorder = USHRT_MAX, nBottomBorder = USHRT_MAX;
     850             :             sal_uInt16 nBorderMask =
     851             :             MergeBoxBorders( pBox, nRow, nCol, nRowSpan, nColSpan,
     852           0 :                                 nTopBorder, nBottomBorder );
     853             : 
     854           0 :             SwWriteTableCol *pCol = aCols[nCol];
     855           0 :             if( !(nBorderMask & 4) )
     856           0 :                 pCol->bLeftBorder = false;
     857             : 
     858           0 :             pCol = aCols[nCol+nColSpan-1];
     859           0 :             if( !(nBorderMask & 8) )
     860           0 :                 pCol->bRightBorder = false;
     861             : 
     862           0 :             if( !(nBorderMask & 1) )
     863           0 :                 pRow->bTopBorder = false;
     864             : 
     865           0 :             SwWriteTableRow *pEndRow = aRows[nRow+nRowSpan-1];
     866           0 :             if( !(nBorderMask & 2) )
     867           0 :                 pEndRow->bBottomBorder = false;
     868             : 
     869             :             // Die Hoehe braucht nur einmal geschieben werden
     870           0 :             if( nHeight )
     871           0 :                 bHeightExported = sal_True;
     872             :         }
     873             :     }
     874             : 
     875             :     // Einige Twip-Werte an Pixel-Grenzen anpassen
     876           0 :     if( bCollectBorderWidth && !nBorder )
     877           0 :         nBorder = nInnerBorder;
     878           0 : }
     879             : 
     880          10 : SwWriteTable::~SwWriteTable()
     881             : {
     882          10 : }
     883             : 
     884             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10