/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sw.hxx" #include #include #include #include #include #include #include #include #include #include #include #include using namespace ::com::sun::star; SV_IMPL_PTRARR( SwWriteTableCells, SwWriteTableCellPtr ) SV_IMPL_OP_PTRARR_SORT( SwWriteTableRows, SwWriteTableRowPtr ) SV_IMPL_OP_PTRARR_SORT( SwWriteTableCols, SwWriteTableColPtr ) //----------------------------------------------------------------------- sal_Int16 SwWriteTableCell::GetVertOri() const { sal_Int16 eCellVertOri = text::VertOrientation::TOP; if( pBox->GetSttNd() ) { const SfxItemSet& rItemSet = pBox->GetFrmFmt()->GetAttrSet(); const SfxPoolItem *pItem; if( SFX_ITEM_SET == rItemSet.GetItemState( RES_VERT_ORIENT, sal_False, &pItem ) ) { sal_Int16 eBoxVertOri = ((const SwFmtVertOrient *)pItem)->GetVertOrient(); if( text::VertOrientation::CENTER==eBoxVertOri || text::VertOrientation::BOTTOM==eBoxVertOri) eCellVertOri = eBoxVertOri; } } return eCellVertOri; } //----------------------------------------------------------------------- SwWriteTableRow::SwWriteTableRow( long nPosition, sal_Bool bUseLayoutHeights ) : pBackground(0), nPos(nPosition), mbUseLayoutHeights(bUseLayoutHeights), nTopBorder(USHRT_MAX), nBottomBorder(USHRT_MAX), bTopBorder(true), bBottomBorder(true) { } SwWriteTableCell *SwWriteTableRow::AddCell( const SwTableBox *pBox, sal_uInt16 nRow, sal_uInt16 nCol, sal_uInt16 nRowSpan, sal_uInt16 nColSpan, long nHeight, const SvxBrushItem *pBackgroundBrush ) { SwWriteTableCell *pCell = new SwWriteTableCell( pBox, nRow, nCol, nRowSpan, nColSpan, nHeight, pBackgroundBrush ); aCells.Insert( pCell, aCells.Count() ); return pCell; } //----------------------------------------------------------------------- SwWriteTableCol::SwWriteTableCol(sal_uInt32 nPosition) : nPos(nPosition), nWidthOpt(0), bRelWidthOpt(false), bOutWidth(true), bLeftBorder(true), bRightBorder(true) { } //----------------------------------------------------------------------- sal_uInt32 SwWriteTable::GetBoxWidth( const SwTableBox *pBox ) { const SwFrmFmt *pFmt = pBox->GetFrmFmt(); const SwFmtFrmSize& aFrmSize= (const SwFmtFrmSize&)pFmt->GetFmtAttr( RES_FRM_SIZE ); return sal::static_int_cast(aFrmSize.GetSize().Width()); } long SwWriteTable::GetLineHeight( const SwTableLine *pLine ) { #ifdef DBG_UTIL sal_Bool bOldGetLineHeightCalled = bGetLineHeightCalled; bGetLineHeightCalled = sal_True; #endif long nHeight = 0; if( bUseLayoutHeights ) { // Erstmal versuchen wir die Hoehe ueber das Layout zu bekommen bool bLayoutAvailable = false; nHeight = pLine->GetTableLineHeight(bLayoutAvailable); if( nHeight > 0 ) return nHeight; // Wenn kein Layout gefunden wurde, gehen wir von festen Hoehen aus. // --> FME 2007-3-26 #i60390# in some cases we still want to continue // to use the layout heights even if one of the rows has a height of 0 // ('hidden' rows) // <-- bUseLayoutHeights = bLayoutAvailable; /*sal_False;*/ #ifdef DBG_UTIL ASSERT( bLayoutAvailable || !bOldGetLineHeightCalled, "Layout ungueltig?" ); #endif } const SwTableBoxes& rBoxes = pLine->GetTabBoxes(); sal_uInt16 nBoxes = rBoxes.Count(); for( sal_uInt16 nBox=0; nBoxGetSttNd() ) { if( nHeight < ROW_DFLT_HEIGHT ) nHeight = ROW_DFLT_HEIGHT; } else { long nTmp = 0; const SwTableLines &rLines = pBox->GetTabLines(); for( sal_uInt16 nLine=0; nLineGetUpper(); if( !pLine ) return 0; const SwFrmFmt *pLineFrmFmt = pLine->GetFrmFmt(); const SfxPoolItem* pItem; const SfxItemSet& rItemSet = pLineFrmFmt->GetAttrSet(); long nHeight = 0; if( SFX_ITEM_SET == rItemSet.GetItemState( RES_FRM_SIZE, sal_True, &pItem )) nHeight = ((SwFmtFrmSize*)pItem)->GetHeight(); return nHeight; } const SvxBrushItem *SwWriteTable::GetLineBrush( const SwTableBox *pBox, SwWriteTableRow *pRow ) { const SwTableLine *pLine = pBox->GetUpper(); while( pLine ) { const SwFrmFmt *pLineFrmFmt = pLine->GetFrmFmt(); const SfxPoolItem* pItem; const SfxItemSet& rItemSet = pLineFrmFmt->GetAttrSet(); if( SFX_ITEM_SET == rItemSet.GetItemState( RES_BACKGROUND, sal_False, &pItem ) ) { if( !pLine->GetUpper() ) { if( !pRow->GetBackground() ) pRow->SetBackground( (const SvxBrushItem *)pItem ); pItem = 0; } return (const SvxBrushItem *)pItem; } pBox = pLine->GetUpper(); pLine = pBox ? pBox->GetUpper() : 0; } return 0; } void SwWriteTable::MergeBorders( const SvxBorderLine* pBorderLine, sal_Bool bTable ) { if( (sal_uInt32)-1 == nBorderColor ) { Color aGrayColor( COL_GRAY ); if( !pBorderLine->GetColor().IsRGBEqual( aGrayColor ) ) nBorderColor = pBorderLine->GetColor().GetColor(); } if( !bCollectBorderWidth ) return; sal_uInt16 nOutWidth = pBorderLine->GetOutWidth(); if( bTable ) { if( nOutWidth && (!nBorder || nOutWidth < nBorder) ) nBorder = nOutWidth; } else { if( nOutWidth && (!nInnerBorder || nOutWidth < nInnerBorder) ) nInnerBorder = nOutWidth; } sal_uInt16 nDist = pBorderLine->GetInWidth() ? pBorderLine->GetDistance() : 0; if( nDist && (!nCellSpacing || nDist < nCellSpacing) ) nCellSpacing = nDist; } sal_uInt16 SwWriteTable::MergeBoxBorders( const SwTableBox *pBox, sal_uInt16 nRow, sal_uInt16 nCol, sal_uInt16 nRowSpan, sal_uInt16 nColSpan, sal_uInt16& rTopBorder, sal_uInt16 &rBottomBorder ) { sal_uInt16 nBorderMask = 0; const SwFrmFmt *pFrmFmt = pBox->GetFrmFmt(); const SvxBoxItem& rBoxItem = (const SvxBoxItem&)pFrmFmt->GetFmtAttr( RES_BOX ); if( rBoxItem.GetTop() ) { nBorderMask |= 1; MergeBorders( rBoxItem.GetTop(), nRow==0 ); rTopBorder = rBoxItem.GetTop()->GetOutWidth(); } if( rBoxItem.GetLeft() ) { nBorderMask |= 4; MergeBorders( rBoxItem.GetLeft(), nCol==0 ); } if( rBoxItem.GetBottom() ) { nBorderMask |= 2; MergeBorders( rBoxItem.GetBottom(), nRow+nRowSpan==aRows.Count() ); rBottomBorder = rBoxItem.GetBottom()->GetOutWidth(); } if( rBoxItem.GetRight() ) { nBorderMask |= 8; MergeBorders( rBoxItem.GetRight(), nCol+nColSpan==aCols.Count() ); } // If any distance is set, the smallest one is used. This holds for // the four distance of a box as well as for the distances of different // boxes. if( bCollectBorderWidth ) { sal_uInt16 nDist = rBoxItem.GetDistance( BOX_LINE_TOP ); if( nDist && (!nCellPadding || nDist < nCellPadding) ) nCellPadding = nDist; nDist = rBoxItem.GetDistance( BOX_LINE_BOTTOM ); if( nDist && (!nCellPadding || nDist < nCellPadding) ) nCellPadding = nDist; nDist = rBoxItem.GetDistance( BOX_LINE_LEFT ); if( nDist && (!nCellPadding || nDist < nCellPadding) ) nCellPadding = nDist; nDist = rBoxItem.GetDistance( BOX_LINE_RIGHT ); if( nDist && (!nCellPadding || nDist < nCellPadding) ) nCellPadding = nDist; } return nBorderMask; } sal_uInt32 SwWriteTable::GetRawWidth( sal_uInt16 nCol, sal_uInt16 nColSpan ) const { sal_uInt32 nWidth = aCols[nCol+nColSpan-1]->GetPos(); if( nCol > 0 ) nWidth = nWidth - aCols[nCol-1]->GetPos(); return nWidth; } sal_uInt16 SwWriteTable::GetLeftSpace( sal_uInt16 nCol ) const { sal_uInt16 nSpace = nCellPadding + nCellSpacing; // In der ersten Spalte auch noch die Liniendicke abziehen if( nCol==0 ) { nSpace = nSpace + nLeftSub; const SwWriteTableCol *pCol = aCols[nCol]; if( pCol->HasLeftBorder() ) nSpace = nSpace + nBorder; } return nSpace; } sal_uInt16 SwWriteTable::GetRightSpace( sal_uInt16 nCol, sal_uInt16 nColSpan ) const { sal_uInt16 nSpace = nCellPadding; // In der letzten Spalte noch einmal zusaetzlich CELLSPACING und // und die Liniendicke abziehen if( nCol+nColSpan==aCols.Count() ) { nSpace += (nCellSpacing + nRightSub); const SwWriteTableCol *pCol = aCols[nCol+nColSpan-1]; if( pCol->HasRightBorder() ) nSpace = nSpace + nBorder; } return nSpace; } sal_uInt16 SwWriteTable::GetAbsWidth( sal_uInt16 nCol, sal_uInt16 nColSpan ) const { sal_uInt32 nWidth = GetRawWidth( nCol, nColSpan ); if( nBaseWidth != nTabWidth ) { nWidth *= nTabWidth; nWidth /= nBaseWidth; } nWidth -= GetLeftSpace( nCol ) + GetRightSpace( nCol, nColSpan ); ASSERT( nWidth > 0, "Spaltenbreite <= 0. OK?" ); return nWidth > 0 ? (sal_uInt16)nWidth : 0; } sal_uInt16 SwWriteTable::GetRelWidth( sal_uInt16 nCol, sal_uInt16 nColSpan ) const { long nWidth = GetRawWidth( nCol, nColSpan ); return (sal_uInt16)(long)Fraction( nWidth*256 + GetBaseWidth()/2, GetBaseWidth() ); } sal_uInt16 SwWriteTable::GetPrcWidth( sal_uInt16 nCol, sal_uInt16 nColSpan ) const { long nWidth = GetRawWidth( nCol, nColSpan ); // sieht komisch aus, ist aber nichts anderes als // [(100 * nWidth) + .5] ohne Rundungsfehler return (sal_uInt16)(long)Fraction( nWidth*100 + GetBaseWidth()/2, GetBaseWidth() ); } long SwWriteTable::GetAbsHeight( long nRawHeight, sal_uInt16 nRow, sal_uInt16 nRowSpan ) const { nRawHeight -= (2*nCellPadding + nCellSpacing); // In der ersten Zeile noch einmal zusaetzlich CELLSPACING und // und die Liniendicke abziehen const SwWriteTableRow *pRow = 0; if( nRow==0 ) { nRawHeight -= nCellSpacing; pRow = aRows[nRow]; if( pRow->HasTopBorder() ) nRawHeight -= nBorder; } // In der letzten Zeile noch die Liniendicke abziehen if( nRow+nRowSpan==aRows.Count() ) { if( !pRow || nRowSpan > 1 ) pRow = aRows[nRow+nRowSpan-1]; if( pRow->HasBottomBorder() ) nRawHeight -= nBorder; } ASSERT( nRawHeight > 0, "Zeilenheohe <= 0. OK?" ); return nRawHeight > 0 ? nRawHeight : 0; } sal_Bool SwWriteTable::ShouldExpandSub(const SwTableBox *pBox, sal_Bool /*bExpandedBefore*/, sal_uInt16 nDepth) const { return !pBox->GetSttNd() && nDepth > 0; } void SwWriteTable::CollectTableRowsCols( long nStartRPos, sal_uInt32 nStartCPos, long nParentLineHeight, sal_uInt32 nParentLineWidth, const SwTableLines& rLines, sal_uInt16 nDepth ) { sal_Bool bSubExpanded = sal_False; sal_uInt16 nLines = rLines.Count(); #ifdef DBG_UTIL sal_uInt32 nEndCPos = 0; #endif long nRPos = nStartRPos; for( sal_uInt16 nLine = 0; nLine < nLines; nLine++ ) { /*const*/ SwTableLine *pLine = rLines[nLine]; long nOldRPos = nRPos; if( nLine < nLines-1 || nParentLineHeight==0 ) { long nLineHeight = GetLineHeight( pLine ); nRPos += nLineHeight; if( nParentLineHeight && nStartRPos + nParentLineHeight <= nRPos ) { /* If you have corrupt line height information, e.g. breaking rows in complex table layout, you may run into this robust code. It's not allowed that subrows leaves their parentrow. If this would happen the line height of subrow is reduced to a part of the remaining height */ ASSERT( sal_False, "Corrupt line height I" ); nRPos -= nLineHeight; nLineHeight = nStartRPos + nParentLineHeight - nRPos; // remaining parent height nLineHeight /= nLines - nLine; // divided through the number of remaining sub rows nRPos += nLineHeight; } SwWriteTableRow *pRow = new SwWriteTableRow( nRPos, bUseLayoutHeights); sal_uInt16 nRow; if( aRows.Seek_Entry( pRow, &nRow ) ) delete pRow; else aRows.Insert( pRow ); } else { #ifdef DBG_UTIL long nCheckPos = nRPos + GetLineHeight( pLine ); #endif nRPos = nStartRPos + nParentLineHeight; #ifdef DBG_UTIL SwWriteTableRow aRow( nStartRPos + nParentLineHeight, bUseLayoutHeights ); ASSERT( aRows.Seek_Entry(&aRow), "Parent-Zeile nicht gefunden" ); SwWriteTableRow aRowCheckPos(nCheckPos,bUseLayoutHeights); SwWriteTableRow aRowRPos(nRPos,bUseLayoutHeights); ASSERT( !bUseLayoutHeights || aRowCheckPos == aRowRPos, "Hoehe der Zeilen stimmt nicht mit Parent ueberein" ); #endif } // Fuer alle Boxen der Zeile ggf. eine Spalte einfuegen const SwTableBoxes& rBoxes = pLine->GetTabBoxes(); sal_uInt16 nBoxes = rBoxes.Count(); sal_uInt32 nCPos = nStartCPos; for( sal_uInt16 nBox=0; nBoxGetTabLines(), nDepth-1 ); bSubExpanded = sal_True; } } } } void SwWriteTable::FillTableRowsCols( long nStartRPos, sal_uInt16 nStartRow, sal_uInt32 nStartCPos, sal_uInt16 nStartCol, long nParentLineHeight, sal_uInt32 nParentLineWidth, const SwTableLines& rLines, const SvxBrushItem* pParentBrush, sal_uInt16 nDepth, sal_uInt16 nNumOfHeaderRows ) { sal_uInt16 nLines = rLines.Count(); sal_Bool bSubExpanded = sal_False; // Festlegen der Umrandung long nRPos = nStartRPos; sal_uInt16 nRow = nStartRow; for( sal_uInt16 nLine = 0; nLine < nLines; nLine++ ) { const SwTableLine *pLine = rLines[nLine]; // Position der letzten ueberdeckten Zeile ermitteln long nOldRPos = nRPos; if( nLine < nLines-1 || nParentLineHeight==0 ) { long nLineHeight = GetLineHeight( pLine ); nRPos += nLineHeight; if( nParentLineHeight && nStartRPos + nParentLineHeight <= nRPos ) { /* See comment in CollectTableRowCols */ ASSERT( sal_False, "Corrupt line height II" ); nRPos -= nLineHeight; nLineHeight = nStartRPos + nParentLineHeight - nRPos; // remaining parent height nLineHeight /= nLines - nLine; // divided through the number of remaining sub rows nRPos += nLineHeight; } } else nRPos = nStartRPos + nParentLineHeight; // Und ihren Index sal_uInt16 nOldRow = nRow; SwWriteTableRow aRow( nRPos,bUseLayoutHeights ); #ifdef DBG_UTIL sal_Bool bFound = #endif aRows.Seek_Entry( &aRow, &nRow ); ASSERT( bFound, "Wo ist die Zeile geblieben?" ); ASSERT( nOldRow <= nRow, "Don't look back!" ); if( nOldRow > nRow ) { nOldRow = nRow; if( nOldRow ) --nOldRow; } SwWriteTableRow *pRow = aRows[nOldRow]; SwWriteTableRow *pEndRow = aRows[nRow]; // if( nLine==0 && nParentLineHeight==0 ) if( nLine+1==nNumOfHeaderRows && nParentLineHeight==0 ) nHeadEndRow = nRow; const SwTableBoxes& rBoxes = pLine->GetTabBoxes(); const SwFrmFmt *pLineFrmFmt = pLine->GetFrmFmt(); const SfxPoolItem* pItem; const SfxItemSet& rItemSet = pLineFrmFmt->GetAttrSet(); long nHeight = 0; if( SFX_ITEM_SET == rItemSet.GetItemState( RES_FRM_SIZE, sal_True, &pItem )) nHeight = ((SwFmtFrmSize*)pItem)->GetHeight(); const SvxBrushItem *pBrushItem, *pLineBrush = pParentBrush; if( SFX_ITEM_SET == rItemSet.GetItemState( RES_BACKGROUND, sal_False, &pItem ) ) { pLineBrush = (const SvxBrushItem *)pItem; // Wenn die Zeile die gesamte Tabelle umspannt, koennen // Wir den Hintergrund an der Zeile ausgeben. Sonst muessen // wir in an den Zelle ausgeben. sal_Bool bOutAtRow = !nParentLineWidth; if( !bOutAtRow && nStartCPos==0 ) { sal_uInt16 nEndCol; SwWriteTableCol aCol( nParentLineWidth ); bOutAtRow = aCols.Seek_Entry(&aCol,&nEndCol) && nEndCol == aCols.Count()-1; } if( bOutAtRow ) { pRow->SetBackground( pLineBrush ); pBrushItem = 0; } else pBrushItem = pLineBrush; } else { pRow->SetBackground( pLineBrush ); pBrushItem = 0; } sal_uInt16 nBoxes = rBoxes.Count(); sal_uInt32 nCPos = nStartCPos; sal_uInt16 nCol = nStartCol; for( sal_uInt16 nBox=0; nBoxgetRowSpan(); if ( 1 < nAttrRowSpan ) nRowSpan = (sal_uInt16)nAttrRowSpan; else if ( nAttrRowSpan < 1 ) nRowSpan = 0; sal_uInt16 nColSpan = nCol - nOldCol + 1; pRow->AddCell( pBox, nOldRow, nOldCol, nRowSpan, nColSpan, nHeight, pBrushItem ); nHeight = 0; // Die Hoehe braucht nur einmal geschieben werden if( pBox->GetSttNd() ) { sal_uInt16 nTopBorder = USHRT_MAX, nBottomBorder = USHRT_MAX; sal_uInt16 nBorderMask = MergeBoxBorders(pBox, nOldRow, nOldCol, nRowSpan, nColSpan, nTopBorder, nBottomBorder); // #i30094# add a sanity check here to ensure that // we don't access an invalid aCols[] as &nCol // above can be changed. if (!(nBorderMask & 4) && nOldCol < aCols.Count()) { SwWriteTableCol *pCol = aCols[nOldCol]; ASSERT(pCol, "No TableCol found, panic!"); if (pCol) pCol->bLeftBorder = sal_False; } if (!(nBorderMask & 8)) { SwWriteTableCol *pCol = aCols[nCol]; ASSERT(pCol, "No TableCol found, panic!"); if (pCol) pCol->bRightBorder = sal_False; } if (!(nBorderMask & 1)) pRow->bTopBorder = sal_False; else if (!pRow->nTopBorder || nTopBorder < pRow->nTopBorder) pRow->nTopBorder = nTopBorder; if (!(nBorderMask & 2)) pEndRow->bBottomBorder = sal_False; else if ( !pEndRow->nBottomBorder || nBottomBorder < pEndRow->nBottomBorder ) { pEndRow->nBottomBorder = nBottomBorder; } } // MIB: 13.12.2000: Why should a cell that contains a subtable // not have borders? Moreover, switching them, off switches off // the fill border lines between the columns and rows. (#74222#) // else // { // aCols[nOldCol]->bLeftBorder = sal_False; // aCols[nCol]->bRightBorder = sal_False; // pRow->bTopBorder = sal_False; // pEndRow->bBottomBorder = sal_False; // } } else { FillTableRowsCols( nOldRPos, nOldRow, nOldCPos, nOldCol, nRPos-nOldRPos, nCPos-nOldCPos, pBox->GetTabLines(), pLineBrush, nDepth-1, nNumOfHeaderRows ); bSubExpanded = sal_True; } nCol++; // Die naechste Zelle faengt in der nachten Spalte an } nRow++; } } SwWriteTable::SwWriteTable(const SwTableLines& rLines, long nWidth, sal_uInt32 nBWidth, sal_Bool bRel, sal_uInt16 nMaxDepth, sal_uInt16 nLSub, sal_uInt16 nRSub, sal_uInt32 nNumOfRowsToRepeat) : nBorderColor((sal_uInt32)-1), nCellSpacing(0), nCellPadding(0), nBorder(0), nInnerBorder(0), nBaseWidth(nBWidth), nHeadEndRow(USHRT_MAX), nLeftSub(nLSub), nRightSub(nRSub), nTabWidth(nWidth), bRelWidths(bRel), bUseLayoutHeights(true), #ifdef DBG_UTIL bGetLineHeightCalled(false), #endif bColsOption(false), bColTags(true), bLayoutExport(false), bCollectBorderWidth(true) { sal_uInt32 nParentWidth = nBaseWidth + nLeftSub + nRightSub; // Erstmal die Tabellen-Struktur festlegen. Hinter der Tabelle ist in // jedem Fall eine Spalte zu Ende SwWriteTableCol *pCol = new SwWriteTableCol( nParentWidth ); aCols.Insert( pCol ); CollectTableRowsCols( 0, 0, 0, nParentWidth, rLines, nMaxDepth - 1 ); // Und jetzt mit leben fuellen FillTableRowsCols( 0, 0, 0, 0, 0, nParentWidth, rLines, 0, nMaxDepth - 1, static_cast< sal_uInt16 >(nNumOfRowsToRepeat) ); // Einige Twip-Werte an Pixel-Grenzen anpassen if( !nBorder ) nBorder = nInnerBorder; } SwWriteTable::SwWriteTable( const SwHTMLTableLayout *pLayoutInfo ) : nBorderColor((sal_uInt32)-1), nCellSpacing(0), nCellPadding(0), nBorder(0), nInnerBorder(0), nBaseWidth(pLayoutInfo->GetWidthOption()), nHeadEndRow(0), nLeftSub(0), nRightSub(0), nTabWidth(pLayoutInfo->GetWidthOption()), bRelWidths(pLayoutInfo->HasPrcWidthOption()), bUseLayoutHeights(false), #ifdef DBG_UTIL bGetLineHeightCalled(false), #endif bColsOption(pLayoutInfo->HasColsOption()), bColTags(pLayoutInfo->HasColTags()), bLayoutExport(true), bCollectBorderWidth(pLayoutInfo->HaveBordersChanged()) { if( !bCollectBorderWidth ) { nBorder = pLayoutInfo->GetBorder(); nCellPadding = pLayoutInfo->GetCellPadding(); nCellSpacing = pLayoutInfo->GetCellSpacing(); } sal_uInt16 nRow, nCol; sal_uInt16 nCols = pLayoutInfo->GetColCount(); sal_uInt16 nRows = pLayoutInfo->GetRowCount(); // Erstmal die Tabellen-Struktur festlegen. for( nCol=0; nColGetColumn( nCol ); pCol->SetWidthOpt( pLayoutCol->GetWidthOption(), pLayoutCol->IsRelWidthOption() ); } aCols.Insert( pCol ); } for( nRow=0; nRownTopBorder = 0; pRow->nBottomBorder = 0; aRows.Insert( pRow ); } // Und jetzt mit leben fuellen for( nRow=0; nRowGetCell( nRow, nCol ); const SwHTMLTableLayoutCnts *pLayoutCnts = pLayoutCell->GetContents(); // Beginnt die Zelle eigentlich eine Zeile weiter oben oder // weiter vorne? if( ( nRow>0 && pLayoutCnts == pLayoutInfo->GetCell(nRow-1,nCol) ->GetContents() ) || ( nCol>0 && pLayoutCnts == pLayoutInfo->GetCell(nRow,nCol-1) ->GetContents() ) ) { continue; } sal_uInt16 nRowSpan = pLayoutCell->GetRowSpan(); sal_uInt16 nColSpan = pLayoutCell->GetColSpan(); const SwTableBox *pBox = pLayoutCnts->GetTableBox(); ASSERT( pBox, "Tabelle in Tabelle kann nicht ueber Layout exportiert werden" ); long nHeight = bHeightExported ? 0 : GetLineHeight( pBox ); const SvxBrushItem *pBrushItem = GetLineBrush( pBox, pRow ); SwWriteTableCell *pCell = pRow->AddCell( pBox, nRow, nCol, nRowSpan, nColSpan, nHeight, pBrushItem ); pCell->SetWidthOpt( pLayoutCell->GetWidthOption(), pLayoutCell->IsPrcWidthOption() ); sal_uInt16 nTopBorder = USHRT_MAX, nBottomBorder = USHRT_MAX; sal_uInt16 nBorderMask = MergeBoxBorders( pBox, nRow, nCol, nRowSpan, nColSpan, nTopBorder, nBottomBorder ); SwWriteTableCol *pCol = aCols[nCol]; if( !(nBorderMask & 4) ) pCol->bLeftBorder = sal_False; pCol = aCols[nCol+nColSpan-1]; if( !(nBorderMask & 8) ) pCol->bRightBorder = sal_False; if( !(nBorderMask & 1) ) pRow->bTopBorder = sal_False; SwWriteTableRow *pEndRow = aRows[nRow+nRowSpan-1]; if( !(nBorderMask & 2) ) pEndRow->bBottomBorder = sal_False; // Die Hoehe braucht nur einmal geschieben werden if( nHeight ) bHeightExported = sal_True; } } // Einige Twip-Werte an Pixel-Grenzen anpassen if( bCollectBorderWidth && !nBorder ) nBorder = nInnerBorder; } SwWriteTable::~SwWriteTable() { }