summaryrefslogtreecommitdiff
path: root/oox/source/xls/stylesbuffer.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'oox/source/xls/stylesbuffer.cxx')
-rw-r--r--oox/source/xls/stylesbuffer.cxx224
1 files changed, 172 insertions, 52 deletions
diff --git a/oox/source/xls/stylesbuffer.cxx b/oox/source/xls/stylesbuffer.cxx
index 3eac90040667..cd914ceae196 100644
--- a/oox/source/xls/stylesbuffer.cxx
+++ b/oox/source/xls/stylesbuffer.cxx
@@ -69,6 +69,7 @@ using ::com::sun::star::awt::FontDescriptor;
using ::com::sun::star::awt::XDevice;
using ::com::sun::star::awt::XFont2;
using ::com::sun::star::table::BorderLine;
+using ::com::sun::star::table::TableBorder;
using ::com::sun::star::text::XText;
using ::com::sun::star::style::XStyle;
using ::oox::core::FilterBase;
@@ -1398,7 +1399,6 @@ void Alignment::writeToPropertyMap( PropertyMap& rPropMap ) const
rPropMap[ PROP_VertJustify ] <<= maApiData.meVerJustify;
rPropMap[ PROP_WritingMode ] <<= maApiData.mnWritingMode;
rPropMap[ PROP_RotateAngle ] <<= maApiData.mnRotation;
- rPropMap[ PROP_RotateReference ] <<= ::com::sun::star::table::CellVertJustify_STANDARD; // rotation reference
rPropMap[ PROP_Orientation ] <<= maApiData.meOrientation;
rPropMap[ PROP_ParaIndent ] <<= maApiData.mnIndent;
rPropMap[ PROP_IsTextWrapped ] <<= maApiData.mbWrapText;
@@ -1517,6 +1517,57 @@ ApiBorderData::ApiBorderData() :
{
}
+bool ApiBorderData::hasAnyOuterBorder() const
+{
+ return
+ (maBorder.IsTopLineValid && (maBorder.TopLine.OuterLineWidth > 0)) ||
+ (maBorder.IsBottomLineValid && (maBorder.BottomLine.OuterLineWidth > 0)) ||
+ (maBorder.IsLeftLineValid && (maBorder.LeftLine.OuterLineWidth > 0)) ||
+ (maBorder.IsRightLineValid && (maBorder.RightLine.OuterLineWidth > 0));
+}
+
+namespace {
+
+bool operator==( const BorderLine& rLeft, const BorderLine& rRight )
+{
+ return
+ (rLeft.Color == rRight.Color) &&
+ (rLeft.InnerLineWidth == rRight.InnerLineWidth) &&
+ (rLeft.OuterLineWidth == rRight.OuterLineWidth) &&
+ (rLeft.LineDistance == rRight.LineDistance);
+}
+
+bool operator==( const TableBorder& rLeft, const TableBorder& rRight )
+{
+ return
+ (rLeft.TopLine == rRight.TopLine) &&
+ (rLeft.IsTopLineValid == rRight.IsTopLineValid) &&
+ (rLeft.BottomLine == rRight.BottomLine) &&
+ (rLeft.IsBottomLineValid == rRight.IsBottomLineValid) &&
+ (rLeft.LeftLine == rRight.LeftLine) &&
+ (rLeft.IsLeftLineValid == rRight.IsLeftLineValid) &&
+ (rLeft.RightLine == rRight.RightLine) &&
+ (rLeft.IsRightLineValid == rRight.IsRightLineValid) &&
+ (rLeft.HorizontalLine == rRight.HorizontalLine) &&
+ (rLeft.IsHorizontalLineValid == rRight.IsHorizontalLineValid) &&
+ (rLeft.VerticalLine == rRight.VerticalLine) &&
+ (rLeft.IsVerticalLineValid == rRight.IsVerticalLineValid) &&
+ (rLeft.Distance == rRight.Distance) &&
+ (rLeft.IsDistanceValid == rRight.IsDistanceValid);
+}
+
+} // namespace
+
+bool operator==( const ApiBorderData& rLeft, const ApiBorderData& rRight )
+{
+ return
+ (rLeft.maBorder == rRight.maBorder) &&
+ (rLeft.maTLtoBR == rRight.maTLtoBR) &&
+ (rLeft.maBLtoTR == rRight.maBLtoTR) &&
+ (rLeft.mbBorderUsed == rRight.mbBorderUsed) &&
+ (rLeft.mbDiagUsed == rRight.mbDiagUsed);
+}
+
// ============================================================================
namespace {
@@ -1820,6 +1871,14 @@ ApiSolidFillData::ApiSolidFillData() :
{
}
+bool operator==( const ApiSolidFillData& rLeft, const ApiSolidFillData& rRight )
+{
+ return
+ (rLeft.mnColor == rRight.mnColor) &&
+ (rLeft.mbTransparent == rRight.mbTransparent) &&
+ (rLeft.mbUsed == rRight.mbUsed);
+}
+
// ============================================================================
namespace {
@@ -2132,7 +2191,8 @@ XfModel::XfModel() :
Xf::Xf( const WorkbookHelper& rHelper ) :
WorkbookHelper( rHelper ),
maAlignment( rHelper ),
- maProtection( rHelper )
+ maProtection( rHelper ),
+ meRotationRef( ::com::sun::star::table::CellVertJustify_STANDARD )
{
}
@@ -2315,13 +2375,46 @@ void Xf::importXf( BiffInputStream& rStrm )
void Xf::finalizeImport()
{
+ StylesBuffer& rStyles = getStyles();
+
// alignment and protection
maAlignment.finalizeImport();
maProtection.finalizeImport();
- // update used flags from cell style
- if( maModel.mbCellXf )
- if( const Xf* pStyleXf = getStyles().getStyleXf( maModel.mnStyleXfId ).get() )
- updateUsedFlags( *pStyleXf );
+
+ /* Enables the used flags, if the formatting attributes differ from the
+ style XF. In cell XFs Excel uses the cell attributes, if they differ
+ from the parent style XF (even if the used flag is switched off).
+ #109899# ...or if the respective flag is not set in parent style XF.
+ */
+ const Xf* pStyleXf = isCellXf() ? rStyles.getStyleXf( maModel.mnStyleXfId ).get() : 0;
+ if( pStyleXf )
+ {
+ const XfModel& rStyleData = pStyleXf->maModel;
+ if( !maModel.mbFontUsed )
+ maModel.mbFontUsed = !rStyleData.mbFontUsed || (maModel.mnFontId != rStyleData.mnFontId);
+ if( !maModel.mbNumFmtUsed )
+ maModel.mbNumFmtUsed = !rStyleData.mbNumFmtUsed || (maModel.mnNumFmtId != rStyleData.mnNumFmtId);
+ if( !maModel.mbAlignUsed )
+ maModel.mbAlignUsed = !rStyleData.mbAlignUsed || !(maAlignment.getApiData() == pStyleXf->maAlignment.getApiData());
+ if( !maModel.mbProtUsed )
+ maModel.mbProtUsed = !rStyleData.mbProtUsed || !(maProtection.getApiData() == pStyleXf->maProtection.getApiData());
+ if( !maModel.mbBorderUsed )
+ maModel.mbBorderUsed = !rStyleData.mbBorderUsed || !rStyles.equalBorders( maModel.mnBorderId, rStyleData.mnBorderId );
+ if( !maModel.mbAreaUsed )
+ maModel.mbAreaUsed = !rStyleData.mbAreaUsed || !rStyles.equalFills( maModel.mnFillId, rStyleData.mnFillId );
+ }
+
+ /* #i38709# Decide which rotation reference mode to use. If any outer
+ border line of the cell is set (either explicitly or via cell style),
+ and the cell contents are rotated, set rotation reference to bottom of
+ cell. This causes the borders to be painted rotated with the text. */
+ if( const Alignment* pAlignment = maModel.mbAlignUsed ? &maAlignment : (pStyleXf ? &pStyleXf->maAlignment : 0) )
+ {
+ sal_Int32 nBorderId = maModel.mbBorderUsed ? maModel.mnBorderId : (pStyleXf ? pStyleXf->maModel.mnBorderId : -1);
+ if( const Border* pBorder = rStyles.getBorder( nBorderId ).get() )
+ if( (pAlignment->getApiData().mnRotation != 0) && pBorder->getApiData().hasAnyOuterBorder() )
+ meRotationRef = ::com::sun::star::table::CellVertJustify_BOTTOM;
+ }
}
FontRef Xf::getFont() const
@@ -2341,7 +2434,7 @@ void Xf::writeToPropertyMap( PropertyMap& rPropMap ) const
StylesBuffer& rStyles = getStyles();
// create and set cell style
- if( maModel.mbCellXf )
+ if( isCellXf() )
rPropMap[ PROP_CellStyle ] <<= rStyles.createCellStyle( maModel.mnStyleXfId );
if( maModel.mbFontUsed )
@@ -2356,6 +2449,8 @@ void Xf::writeToPropertyMap( PropertyMap& rPropMap ) const
rStyles.writeBorderToPropertyMap( rPropMap, maModel.mnBorderId );
if( maModel.mbAreaUsed )
rStyles.writeFillToPropertyMap( rPropMap, maModel.mnFillId );
+ if( maModel.mbAlignUsed || maModel.mbBorderUsed )
+ rPropMap[ PROP_RotateReference ] <<= meRotationRef;
}
void Xf::writeToPropertySet( PropertySet& rPropSet ) const
@@ -2371,37 +2466,15 @@ void Xf::setBiffUsedFlags( sal_uInt8 nUsedFlags )
- In cell XFs a *set* bit means a used attribute.
- In style XFs a *cleared* bit means a used attribute.
The boolean flags always store true, if the attribute is used.
- The "maModel.mbCellXf == getFlag(...)" construct evaluates to true in
- both mentioned cases: cell XF and set bit; or style XF and cleared bit.
- */
- maModel.mbFontUsed = maModel.mbCellXf == getFlag( nUsedFlags, BIFF_XF_FONT_USED );
- maModel.mbNumFmtUsed = maModel.mbCellXf == getFlag( nUsedFlags, BIFF_XF_NUMFMT_USED );
- maModel.mbAlignUsed = maModel.mbCellXf == getFlag( nUsedFlags, BIFF_XF_ALIGN_USED );
- maModel.mbProtUsed = maModel.mbCellXf == getFlag( nUsedFlags, BIFF_XF_PROT_USED );
- maModel.mbBorderUsed = maModel.mbCellXf == getFlag( nUsedFlags, BIFF_XF_BORDER_USED );
- maModel.mbAreaUsed = maModel.mbCellXf == getFlag( nUsedFlags, BIFF_XF_AREA_USED );
-}
-
-void Xf::updateUsedFlags( const Xf& rStyleXf )
-{
- /* Enables the used flags, if the formatting attributes differ from the
- passed style XF. In cell XFs Excel uses the cell attributes, if they
- differ from the parent style XF.
- #109899# ...or if the respective flag is not set in parent style XF.
+ The "isCellXf() == getFlag(...)" construct evaluates to true in both
+ mentioned cases: cell XF and set bit; or style XF and cleared bit.
*/
- const XfModel& rStyleData = rStyleXf.maModel;
- if( !maModel.mbFontUsed )
- maModel.mbFontUsed = !rStyleData.mbFontUsed || (maModel.mnFontId != rStyleData.mnFontId);
- if( !maModel.mbNumFmtUsed )
- maModel.mbNumFmtUsed = !rStyleData.mbNumFmtUsed || (maModel.mnNumFmtId != rStyleData.mnNumFmtId);
- if( !maModel.mbAlignUsed )
- maModel.mbAlignUsed = !rStyleData.mbAlignUsed || !(maAlignment.getApiData() == rStyleXf.maAlignment.getApiData());
- if( !maModel.mbProtUsed )
- maModel.mbProtUsed = !rStyleData.mbProtUsed || !(maProtection.getApiData() == rStyleXf.maProtection.getApiData());
- if( !maModel.mbBorderUsed )
- maModel.mbBorderUsed = !rStyleData.mbBorderUsed || (maModel.mnBorderId != rStyleData.mnBorderId);
- if( !maModel.mbAreaUsed )
- maModel.mbAreaUsed = !rStyleData.mbAreaUsed || (maModel.mnFillId != rStyleData.mnFillId);
+ maModel.mbFontUsed = isCellXf() == getFlag( nUsedFlags, BIFF_XF_FONT_USED );
+ maModel.mbNumFmtUsed = isCellXf() == getFlag( nUsedFlags, BIFF_XF_NUMFMT_USED );
+ maModel.mbAlignUsed = isCellXf() == getFlag( nUsedFlags, BIFF_XF_ALIGN_USED );
+ maModel.mbProtUsed = isCellXf() == getFlag( nUsedFlags, BIFF_XF_PROT_USED );
+ maModel.mbBorderUsed = isCellXf() == getFlag( nUsedFlags, BIFF_XF_BORDER_USED );
+ maModel.mbAreaUsed = isCellXf() == getFlag( nUsedFlags, BIFF_XF_AREA_USED );
}
// ============================================================================
@@ -3133,11 +3206,12 @@ void StylesBuffer::importFormat( BiffInputStream& rStrm )
void StylesBuffer::importXf( BiffInputStream& rStrm )
{
XfRef xXf( new Xf( *this ) );
- // store XF in both lists (except BIFF2 which does not support cell styles)
- maCellXfs.push_back( xXf );
- if( getBiff() != BIFF2 )
- maStyleXfs.push_back( xXf );
xXf->importXf( rStrm );
+
+ XfRef xCellXf, xStyleXf;
+ (xXf->isCellXf() ? xCellXf : xStyleXf) = xXf;
+ maCellXfs.push_back( xCellXf );
+ maStyleXfs.push_back( xStyleXf );
}
void StylesBuffer::importStyle( BiffInputStream& rStrm )
@@ -3156,20 +3230,11 @@ void StylesBuffer::finalizeImport()
// borders and fills
maBorders.forEachMem( &Border::finalizeImport );
maFills.forEachMem( &Fill::finalizeImport );
-
- /* Style XFs and cell XFs. The BIFF format stores cell XFs and style XFs
- mixed in a single list. The import filter has stored the XFs in both
- lists to make the getStyleXf() function working correctly (e.g. for
- retrieving the default font, see getDefaultFont() function), except for
- BIFF2 which does not support cell styles at all. Therefore, if in BIFF
- filter mode, we do not need to finalize the cell styles list. */
- if( getFilterType() == FILTER_OOX )
- maStyleXfs.forEachMem( &Xf::finalizeImport );
+ // style XFs and cell XFs
+ maStyleXfs.forEachMem( &Xf::finalizeImport );
maCellXfs.forEachMem( &Xf::finalizeImport );
-
// built-in and user defined cell styles
maCellStyles.finalizeImport();
-
// differential formatting (for conditional formatting)
maDxfs.forEachMem( &Dxf::finalizeImport );
}
@@ -3184,6 +3249,11 @@ FontRef StylesBuffer::getFont( sal_Int32 nFontId ) const
return maFonts.get( nFontId );
}
+BorderRef StylesBuffer::getBorder( sal_Int32 nBorderId ) const
+{
+ return maBorders.get( nBorderId );
+}
+
XfRef StylesBuffer::getCellXf( sal_Int32 nXfId ) const
{
return maCellXfs.get( nXfId );
@@ -3225,6 +3295,56 @@ const FontModel& StylesBuffer::getDefaultFontModel() const
return xDefFont.get() ? xDefFont->getModel() : getTheme().getDefaultFontModel();
}
+bool StylesBuffer::equalBorders( sal_Int32 nBorderId1, sal_Int32 nBorderId2 ) const
+{
+ if( nBorderId1 == nBorderId2 )
+ return true;
+
+ switch( getFilterType() )
+ {
+ case FILTER_OOX:
+ // in OOXML, borders are assumed to be unique
+ return false;
+
+ case FILTER_BIFF:
+ {
+ // in BIFF, a new border entry has been created for every XF
+ const Border* pBorder1 = maBorders.get( nBorderId1 ).get();
+ const Border* pBorder2 = maBorders.get( nBorderId2 ).get();
+ return pBorder1 && pBorder2 && (pBorder1->getApiData() == pBorder2->getApiData());
+ }
+
+ case FILTER_UNKNOWN:
+ break;
+ }
+ return false;
+}
+
+bool StylesBuffer::equalFills( sal_Int32 nFillId1, sal_Int32 nFillId2 ) const
+{
+ if( nFillId1 == nFillId2 )
+ return true;
+
+ switch( getFilterType() )
+ {
+ case FILTER_OOX:
+ // in OOXML, fills are assumed to be unique
+ return false;
+
+ case FILTER_BIFF:
+ {
+ // in BIFF, a new fill entry has been created for every XF
+ const Fill* pFill1 = maFills.get( nFillId1 ).get();
+ const Fill* pFill2 = maFills.get( nFillId2 ).get();
+ return pFill1 && pFill2 && (pFill1->getApiData() == pFill2->getApiData());
+ }
+
+ case FILTER_UNKNOWN:
+ break;
+ }
+ return false;
+}
+
OUString StylesBuffer::getDefaultStyleName() const
{
return maCellStyles.getDefaultStyleName();