diff options
Diffstat (limited to 'filter/source/msfilter/msdffimp.cxx')
-rw-r--r-- | filter/source/msfilter/msdffimp.cxx | 859 |
1 files changed, 212 insertions, 647 deletions
diff --git a/filter/source/msfilter/msdffimp.cxx b/filter/source/msfilter/msdffimp.cxx index ed07cd1e5b70..9081122bb4ce 100644 --- a/filter/source/msfilter/msdffimp.cxx +++ b/filter/source/msfilter/msdffimp.cxx @@ -1,31 +1,21 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* +/* + * This file is part of the LibreOffice project. * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. * - * Copyright 2000, 2010 Oracle and/or its affiliates. + * This file incorporates work covered by the following license notice: * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - + * 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 . + */ #include <com/sun/star/embed/Aspects.hpp> @@ -41,6 +31,8 @@ #include <unotools/streamwrap.hxx> #include <comphelper/processfactory.hxx> #include <comphelper/string.hxx> +#include <comphelper/seqstream.hxx> +#include <comphelper/storagehelper.hxx> #include <sot/exchange.hxx> #include <sot/storinfo.hxx> #include <vcl/cvtgrf.hxx> @@ -205,319 +197,11 @@ void Impl_OlePres::Write( SvStream & rStm ) rStm.Seek( nEndPos ); } -//--------------------------------------------------------------------------- -// Hilfs Klassen aus MSDFFDEF.HXX -//--------------------------------------------------------------------------- - -SvStream& operator>>( SvStream& rIn, DffRecordHeader& rRec ) -{ - rRec.nFilePos = rIn.Tell(); - sal_uInt16 nTmp(0); - rIn >> nTmp; - rRec.nImpVerInst = nTmp; - rRec.nRecVer = sal::static_int_cast< sal_uInt8 >(nTmp & 0x000F); - rRec.nRecInstance = nTmp >> 4; - rIn >> rRec.nRecType; - rIn >> rRec.nRecLen; - return rIn; -} - -SvStream& operator>>( SvStream& rIn, DffPropSet& rRec ) -{ - rRec.InitializePropSet(); - - DffRecordHeader aHd; - rIn >> aHd; - sal_uInt32 nPropCount = aHd.nRecInstance; - - // remember FilePos of the ComplexData - sal_uInt32 nComplexDataFilePos = rIn.Tell() + ( nPropCount * 6 ); - - for( sal_uInt32 nPropNum = 0; nPropNum < nPropCount; nPropNum++ ) - { - sal_uInt16 nTmp; - sal_uInt32 nRecType, nContent, nContentEx = 0xffff0000; - rIn >> nTmp - >> nContent; - - nRecType = nTmp & 0x3fff; - - if ( nRecType > 0x3ff ) - break; - if ( ( nRecType & 0x3f ) == 0x3f ) - { // clear flags that have to be cleared - rRec.mpContents[ nRecType ] &= ( ( nContent >> 16 ) ^ 0xffffffff ); - // set flags that have to be set - rRec.mpContents[ nRecType ] |= nContent; - nContentEx |= ( nContent >> 16 ); - rRec.maRecordTypes[ nRecType ] = nContentEx; - } - else - { - DffPropFlags aPropFlag = { 1, 0, 0, 0 }; - if ( nTmp & 0x4000 ) - aPropFlag.bBlip = sal_True; - if ( nTmp & 0x8000 ) - aPropFlag.bComplex = sal_True; - if ( aPropFlag.bComplex && nContent && ( nComplexDataFilePos < aHd.GetRecEndFilePos() ) ) - { - // normally nContent is the complete size of the complex property, - // but this is not always true for IMsoArrays ( what the hell is a IMsoArray ? ) - - // I love special treatments :-( - if ( ( nRecType == DFF_Prop_pVertices ) || ( nRecType == DFF_Prop_pSegmentInfo ) - || ( nRecType == DFF_Prop_fillShadeColors ) || ( nRecType == DFF_Prop_lineDashStyle ) - || ( nRecType == DFF_Prop_pWrapPolygonVertices ) || ( nRecType == DFF_Prop_connectorPoints ) - || ( nRecType == DFF_Prop_Handles ) || ( nRecType == DFF_Prop_pFormulas ) - || ( nRecType == DFF_Prop_textRectangles ) ) - { - // now check if the current content size is possible, or 6 bytes too small - sal_uInt32 nOldPos = rIn.Tell(); - sal_Int16 nNumElem, nNumElemReserved, nSize; - - rIn.Seek( nComplexDataFilePos ); - rIn >> nNumElem >> nNumElemReserved >> nSize; - if ( nNumElemReserved >= nNumElem ) - { - // the size of these array elements is nowhere defined, - // what if the size is negative ? - // ok, we will make it positive and shift it. - // for -16 this works - if ( nSize < 0 ) - nSize = ( -nSize ) >> 2; - sal_uInt32 nDataSize = (sal_uInt32)( nSize * nNumElem ); - - // sometimes the content size is 6 bytes too small (array header information is missing ) - if ( nDataSize == nContent ) - nContent += 6; - - // check if array fits into the PropertyContainer - if ( ( nComplexDataFilePos + nContent ) > aHd.GetRecEndFilePos() ) - nContent = 0; - } - else - nContent = 0; - rIn.Seek( nOldPos ); - } - if ( nContent ) - { - nContentEx = nComplexDataFilePos; // insert the filepos of this property; - nComplexDataFilePos += nContent; // store filepos, that is used for the next complex property - } - else // a complex property needs content - aPropFlag.bSet = sal_False; // otherwise something is wrong - } - rRec.mpContents[ nRecType ] = nContent; - rRec.mpFlags[ nRecType ] = aPropFlag; - rRec.maRecordTypes[ nRecType ] = nContentEx; - } - } - aHd.SeekToEndOfRecord( rIn ); - return rIn; -} - -void DffPropSet::InitializePropSet() const -{ - /* - cmc: - " Boolean properties are grouped in bitfields by property set; note that - the Boolean properties in each property set are contiguous. They are saved - under the property ID of the last Boolean property in the set, and are - placed in the value field in reverse order starting with the last property - in the low bit. " - - e.g. - - fEditedWrap - fBehindDocument - fOnDblClickNotify - fIsButton - fOneD - fHidden - fPrint - - are all part of a group and all are by default false except for fPrint, - which equates to a default bit sequence for the group of 0000001 -> 0x1 - - If at a later stage word sets fBehindDocument away from the default it - will be done by having a property named fPrint whose bitsequence will have - the fBehindDocument bit set. e.g. a DFF_Prop_fPrint with value 0x200020 - has set bit 6 on so as to enable fBehindDocument (as well as disabling - everything else) - */ - - DffPropSet* self = (DffPropSet*) this; - memset( self->mpFlags, 0, 0x400 * sizeof(DffPropFlags) ); - self->maRecordTypes.clear(); - - DffPropFlags nFlags = { 1, 0, 0, 1 }; - - //0x01ff0000; - InitializeProp( DFF_Prop_LockAgainstGrouping, 0x0000, nFlags, 0xffff0000 ); - //0x001f0010; - InitializeProp( DFF_Prop_FitTextToShape, 0x0010, nFlags, 0xffff0000 ); - //0xffff0000; - InitializeProp( DFF_Prop_gtextFStrikethrough, 0x0000, nFlags, 0xffff0000 ); - //0x000f0000; - InitializeProp( DFF_Prop_pictureActive, 0x0000, nFlags, 0xffff0000 ); - //0x003f0039; - InitializeProp( DFF_Prop_fFillOK, 0x0039, nFlags, 0xffff0000 ); - //0x001f001c; - InitializeProp( DFF_Prop_fNoFillHitTest, 0x001c, nFlags, 0xffff0000 ); - //0x001f000e; - InitializeProp( DFF_Prop_fNoLineDrawDash, 0x001e, nFlags, 0xffff0000 ); - //0x00030000; - InitializeProp( DFF_Prop_fshadowObscured, 0x0000, nFlags, 0xffff0000 ); - //0x00010000; - InitializeProp( DFF_Prop_fPerspective, 0x0000, nFlags, 0xffff0000 ); - //0x000f0001; - InitializeProp( DFF_Prop_fc3DLightFace, 0x0001, nFlags, 0xffff0000 ); - //0x001f0016; - InitializeProp( DFF_Prop_fc3DFillHarsh, 0x0016, nFlags, 0xffff0000 ); - //0x001f0000; - InitializeProp( DFF_Prop_fBackground, 0x0000, nFlags, 0xffff0000 ); - //0x00ef0010; - InitializeProp( DFF_Prop_fCalloutLengthSpecified, 0x0010, nFlags, 0xffff0000 ); - //0x00ef0001; - InitializeProp( DFF_Prop_fPrint, 0x0001, nFlags, 0xffff0000 ); - - InitializeProp( DFF_Prop_fillColor, 0xffffff, nFlags, 0xffff0000 ); -} - -void DffPropSet::InitializeProp(sal_uInt32 nKey, sal_uInt32 nContent, DffPropFlags& rFlags, sal_uInt32 nRecordType ) const -{ - DffPropSet* self = (DffPropSet*) this; - self->mpContents[ nKey ] = nContent; - self->mpFlags[ nKey ] = rFlags; - self->maRecordTypes[ nKey ] = nRecordType; -} - - -void DffPropSet::Merge( DffPropSet& rMaster ) const -{ - for ( RecordTypesMap::const_iterator it = rMaster.maRecordTypes.begin(); - it != rMaster.maRecordTypes.end(); ++it ) - { - sal_uInt32 nRecType = it->first; - if ( ( nRecType & 0x3f ) == 0x3f ) // this is something called FLAGS - { - sal_uInt32 nCurrentFlags = mpContents[ nRecType ]; - sal_uInt32 nMergeFlags = rMaster.mpContents[ nRecType ]; - nMergeFlags &= ( nMergeFlags >> 16 ) | 0xffff0000; // clearing low word - nMergeFlags &= ( ( nCurrentFlags & 0xffff0000 ) // remove already hard set - | ( nCurrentFlags >> 16 ) ) ^ 0xffffffff; // attributes from mergeflags - nCurrentFlags &= ( ( nMergeFlags & 0xffff0000 ) // apply zero master bits - | ( nMergeFlags >> 16 ) ) ^ 0xffffffff; - nCurrentFlags |= (sal_uInt16)nMergeFlags; // apply filled master bits - ( (DffPropSet*) this )->mpContents[ nRecType ] = nCurrentFlags; - - - sal_uInt32 nNewContentEx = it->second; - RecordTypesMap::const_iterator it2 = maRecordTypes.find( nRecType ); - if ( it2 != maRecordTypes.end() ) - nNewContentEx |= it2->second; - ( (DffPropSet*) this )->maRecordTypes[ nRecType ] = nNewContentEx; - } - else - { - if ( !IsProperty( nRecType ) || !IsHardAttribute( nRecType ) ) - { - ( (DffPropSet*) this )->mpContents[ nRecType ] = rMaster.mpContents[ nRecType ]; - DffPropFlags nFlags( rMaster.mpFlags[ nRecType ] ); - nFlags.bSoftAttr = sal_True; - ( (DffPropSet*) this )->mpFlags[ nRecType ] = nFlags; - ( (DffPropSet*) this )->maRecordTypes[ nRecType ] = it->second; - } - } - } -} - -sal_Bool DffPropSet::IsHardAttribute( sal_uInt32 nId ) const -{ - sal_Bool bRetValue = sal_True; - nId &= 0x3ff; - if ( ( nId & 0x3f ) >= 48 ) // is this a flag id - { - RecordTypesMap::const_iterator it = maRecordTypes.find( nId | 0x3f ); - if ( it != maRecordTypes.end() ) - { - sal_uInt32 nContentEx = it->second; - bRetValue = ( nContentEx & ( 1 << ( 0xf - ( nId & 0xf ) ) ) ) != 0; - } - } - else - bRetValue = ( mpFlags[ nId ].bSoftAttr == 0 ); - return bRetValue; -}; - -sal_uInt32 DffPropSet::GetPropertyValue( sal_uInt32 nId, sal_uInt32 nDefault ) const -{ - nId &= 0x3ff; - return ( mpFlags[ nId ].bSet ) ? mpContents[ nId ] : nDefault; -}; - -bool DffPropSet::GetPropertyBool( sal_uInt32 nId, bool bDefault ) const -{ - sal_uInt32 nBaseId = nId | 31; // base ID to get the sal_uInt32 property value - sal_uInt32 nMask = 1 << (nBaseId - nId); // bit mask of the boolean property - - sal_uInt32 nPropValue = GetPropertyValue( nBaseId, bDefault ? nMask : 0 ); - return (nPropValue & nMask) != 0; -} - -::rtl::OUString DffPropSet::GetPropertyString( sal_uInt32 nId, SvStream& rStrm ) const -{ - sal_Size nOldPos = rStrm.Tell(); - ::rtl::OUStringBuffer aBuffer; - sal_uInt32 nBufferSize = GetPropertyValue( nId ); - if( (nBufferSize > 0) && SeekToContent( nId, rStrm ) ) - { - sal_Int32 nStrLen = static_cast< sal_Int32 >( nBufferSize / 2 ); - //clip initial size of buffer to something sane in case of silly length - //strings. If there really is a silly amount of data available it still - //works out ok of course - aBuffer.ensureCapacity(std::min(nStrLen,static_cast<sal_Int32>(8192))); - for( sal_Int32 nCharIdx = 0; nCharIdx < nStrLen; ++nCharIdx ) - { - sal_uInt16 nChar = 0; - rStrm >> nChar; - if( nChar > 0 ) - aBuffer.append( static_cast< sal_Unicode >( nChar ) ); - else - break; - } - } - rStrm.Seek( nOldPos ); - return aBuffer.makeStringAndClear(); -} - -sal_Bool DffPropSet::SeekToContent( sal_uInt32 nRecType, SvStream& rStrm ) const -{ - nRecType &= 0x3ff; - if ( mpFlags[ nRecType ].bSet ) - { - if ( mpFlags[ nRecType ].bComplex ) - { - RecordTypesMap::const_iterator it = maRecordTypes.find( nRecType ); - if ( it != maRecordTypes.end() ) - { - sal_uInt32 nOffset = it->second; - if ( nOffset && ( ( nOffset & 0xffff0000 ) != 0xffff0000 ) ) - { - rStrm.Seek( nOffset ); - return sal_True; - } - } - } - } - return sal_False; -} - DffPropertyReader::DffPropertyReader( const SvxMSDffManager& rMan ) : rManager( rMan ), pDefaultPropSet( NULL ) { - InitializePropSet(); + InitializePropSet( DFF_msofbtOPT ); } void DffPropertyReader::SetDefaultPropSet( SvStream& rStCtrl, sal_uInt32 nOffsDgg ) const @@ -555,9 +239,7 @@ void DffPropertyReader::ReadPropSet( SvStream& rIn, void* pClientData ) const rIn >> aRecHd; if ( rManager.SeekToRec( rIn, DFF_msofbtOPT, aRecHd.GetRecEndFilePos() ) ) { - DffPropSet aMasterPropSet; - rIn >> aMasterPropSet; - Merge( aMasterPropSet ); + rIn |= (DffPropertyReader&)*this; } } } @@ -1217,22 +899,43 @@ void DffPropertyReader::ApplyLineAttributes( SfxItemSet& rSet, const MSO_SPT eSh if ( nLineFlags & 8 ) { - // Linienattribute + // Line Attributes sal_Int32 nLineWidth = (sal_Int32)GetPropertyValue( DFF_Prop_lineWidth, 9525 ); + // support LineCap + const MSO_LineCap eLineCap((MSO_LineCap)GetPropertyValue(DFF_Prop_lineEndCapStyle, mso_lineEndCapSquare)); + + switch(eLineCap) + { + default: /* case mso_lineEndCapFlat */ + { + // no need to set, it is the default. If this changes, this needs to be activated + // rSet.Put(XLineCapItem(com::sun::star::drawing::LineCap_BUTT)); + break; + } + case mso_lineEndCapRound: + { + rSet.Put(XLineCapItem(com::sun::star::drawing::LineCap_ROUND)); + break; + } + case mso_lineEndCapSquare: + { + rSet.Put(XLineCapItem(com::sun::star::drawing::LineCap_SQUARE)); + break; + } + } + MSO_LineDashing eLineDashing = (MSO_LineDashing)GetPropertyValue( DFF_Prop_lineDashing, mso_lineSolid ); if ( eLineDashing == mso_lineSolid ) rSet.Put(XLineStyleItem( XLINE_SOLID ) ); else { -// MSO_LineCap eLineCap = (MSO_LineCap)GetPropertyValue( DFF_Prop_lineEndCapStyle, mso_lineEndCapSquare ); - XDashStyle eDash = XDASH_RECT; sal_uInt16 nDots = 1; sal_uInt32 nDotLen = nLineWidth / 360; sal_uInt16 nDashes = 0; sal_uInt32 nDashLen = ( 8 * nLineWidth ) / 360; - sal_uInt32 nDistance = ( 3 * nLineWidth ) / 360;; + sal_uInt32 nDistance = ( 3 * nLineWidth ) / 360; switch ( eLineDashing ) { @@ -1349,24 +1052,6 @@ void DffPropertyReader::ApplyLineAttributes( SfxItemSet& rSet, const MSO_SPT eSh rSet.Put( XLineEndItem( aArrowName, aPolyPoly ) ); rSet.Put( XLineEndCenterItem( bArrowCenter ) ); } - if ( IsProperty( DFF_Prop_lineEndCapStyle ) ) - { - MSO_LineCap eLineCap = (MSO_LineCap)GetPropertyValue( DFF_Prop_lineEndCapStyle ); - const SfxPoolItem* pPoolItem = NULL; - if ( rSet.GetItemState( XATTR_LINEDASH, sal_False, &pPoolItem ) == SFX_ITEM_SET ) - { - XDashStyle eNewStyle = XDASH_RECT; - if ( eLineCap == mso_lineEndCapRound ) - eNewStyle = XDASH_ROUND; - const XDash& rOldDash = ( (const XLineDashItem*)pPoolItem )->GetDashValue(); - if ( rOldDash.GetDashStyle() != eNewStyle ) - { - XDash aNew( rOldDash ); - aNew.SetDashStyle( eNewStyle ); - rSet.Put( XLineDashItem( rtl::OUString(), aNew ) ); - } - } - } } } else @@ -2890,91 +2575,65 @@ void DffPropertyReader::ApplyAttributes( SvStream& rIn, SfxItemSet& rSet ) const ApplyAttributes( rIn, rSet, aDffObjTemp ); } -void DffPropertyReader::ApplyAttributes( SvStream& rIn, SfxItemSet& rSet, const DffObjData& rObjData ) const +void DffPropertyReader::ApplyAttributes( SvStream& rIn, SfxItemSet& rSet, DffObjData& rObjData ) const { sal_Bool bHasShadow = sal_False; - for ( RecordTypesMap::const_iterator it = maRecordTypes.begin(); it != maRecordTypes.end(); ++it ) + if ( IsProperty( DFF_Prop_gtextSize ) ) + rSet.Put( SvxFontHeightItem( rManager.ScalePt( GetPropertyValue( DFF_Prop_gtextSize ) ), 100, EE_CHAR_FONTHEIGHT ) ); + sal_uInt32 nFontAttributes = GetPropertyValue( DFF_Prop_gtextFStrikethrough ); + if ( nFontAttributes & 0x20 ) + rSet.Put( SvxWeightItem( nFontAttributes & 0x20 ? WEIGHT_BOLD : WEIGHT_NORMAL, EE_CHAR_WEIGHT ) ); + if ( nFontAttributes & 0x10 ) + rSet.Put( SvxPostureItem( nFontAttributes & 0x10 ? ITALIC_NORMAL : ITALIC_NONE, EE_CHAR_ITALIC ) ); + if ( nFontAttributes & 0x08 ) + rSet.Put( SvxUnderlineItem( nFontAttributes & 0x08 ? UNDERLINE_SINGLE : UNDERLINE_NONE, EE_CHAR_UNDERLINE ) ); + if ( nFontAttributes & 0x40 ) + rSet.Put( SvxShadowedItem( ( nFontAttributes & 0x40 ) != 0, EE_CHAR_SHADOW ) ); +// if ( nFontAttributes & 0x02 ) +// rSet.Put( SvxCaseMapItem( nFontAttributes & 0x02 ? SVX_CASEMAP_KAPITAELCHEN : SVX_CASEMAP_NOT_MAPPED ) ); + if ( nFontAttributes & 0x01 ) + rSet.Put( SvxCrossedOutItem( nFontAttributes & 0x01 ? STRIKEOUT_SINGLE : STRIKEOUT_NONE, EE_CHAR_STRIKEOUT ) ); + if ( IsProperty( DFF_Prop_fillColor ) ) + rSet.Put( XFillColorItem( String(), rManager.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_fillColor ), DFF_Prop_fillColor ) ) ); + if ( IsProperty( DFF_Prop_shadowType ) ) { - sal_uInt32 nRecType = it->first; - sal_uInt32 nContent = mpContents[ nRecType ]; - switch ( nRecType ) + MSO_ShadowType eShadowType = static_cast< MSO_ShadowType >( GetPropertyValue( DFF_Prop_shadowType ) ); + if( eShadowType != mso_shadowOffset ) { - case DFF_Prop_gtextSize : - rSet.Put( SvxFontHeightItem( rManager.ScalePt( nContent ), 100, EE_CHAR_FONTHEIGHT ) ); - break; - // GeoText - case DFF_Prop_gtextFStrikethrough : - { - if ( nContent & 0x20 ) - rSet.Put( SvxWeightItem( nContent ? WEIGHT_BOLD : WEIGHT_NORMAL, EE_CHAR_WEIGHT ) ); - if ( nContent & 0x10 ) - rSet.Put( SvxPostureItem( nContent ? ITALIC_NORMAL : ITALIC_NONE, EE_CHAR_ITALIC ) ); - if ( nContent & 0x08 ) - rSet.Put( SvxUnderlineItem( nContent ? UNDERLINE_SINGLE : UNDERLINE_NONE, EE_CHAR_UNDERLINE ) ); - if ( nContent & 0x40 ) - rSet.Put(SvxShadowedItem( nContent != 0, EE_CHAR_SHADOW ) ); - if ( nContent & 0x01 ) - rSet.Put( SvxCrossedOutItem( nContent ? STRIKEOUT_SINGLE : STRIKEOUT_NONE, EE_CHAR_STRIKEOUT ) ); - } - break; - - case DFF_Prop_fillColor : - rSet.Put( XFillColorItem( rtl::OUString(), rManager.MSO_CLR_ToColor( nContent, DFF_Prop_fillColor ) ) ); - break; - - // ShadowStyle - case DFF_Prop_shadowType : - { - MSO_ShadowType eShadowType = (MSO_ShadowType)nContent; - if( eShadowType != mso_shadowOffset ) - { - // mso_shadowDouble - // mso_shadowRich - // mso_shadowEmbossOrEngrave - // not possible in LibreOffice, create default shadow with default distance - rSet.Put( SdrShadowXDistItem( 35 ) ); // 0,35 mm shadow distance - rSet.Put( SdrShadowYDistItem( 35 ) ); - } - } - break; - case DFF_Prop_shadowColor : - rSet.Put( SdrShadowColorItem( rtl::OUString(), rManager.MSO_CLR_ToColor( nContent, DFF_Prop_shadowColor ) ) ); - break; - case DFF_Prop_shadowOpacity : - rSet.Put( SdrShadowTransparenceItem( (sal_uInt16)( ( 0x10000 - nContent ) / 655 ) ) ); - break; - case DFF_Prop_shadowOffsetX : - { - sal_Int32 nVal = (sal_Int32)nContent; - rManager.ScaleEmu( nVal ); - if ( nVal ) - rSet.Put( SdrShadowXDistItem( nVal ) ); - } - break; - case DFF_Prop_shadowOffsetY : - { - sal_Int32 nVal = (sal_Int32)nContent; - rManager.ScaleEmu( nVal ); - if ( nVal ) - rSet.Put( SdrShadowYDistItem( nVal ) ); - } - break; - case DFF_Prop_fshadowObscured : - { - bHasShadow = ( nContent & 2 ) != 0; - if ( bHasShadow ) - { - if ( !IsProperty( DFF_Prop_shadowOffsetX ) ) - rSet.Put( SdrShadowXDistItem( 35 ) ); - if ( !IsProperty( DFF_Prop_shadowOffsetY ) ) - rSet.Put( SdrShadowYDistItem( 35 ) ); - } - } - break; + rSet.Put( SdrShadowXDistItem( 35 ) ); // 0,35 mm Schattendistanz + rSet.Put( SdrShadowYDistItem( 35 ) ); + } + } + if ( IsProperty( DFF_Prop_shadowColor ) ) + rSet.Put( SdrShadowColorItem( String(), rManager.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_shadowColor ), DFF_Prop_shadowColor ) ) ); + if ( IsProperty( DFF_Prop_shadowOpacity ) ) + rSet.Put( SdrShadowTransparenceItem( (sal_uInt16)( ( 0x10000 - GetPropertyValue( DFF_Prop_shadowOpacity ) ) / 655 ) ) ); + if ( IsProperty( DFF_Prop_shadowOffsetX ) ) + { + sal_Int32 nVal = static_cast< sal_Int32 >( GetPropertyValue( DFF_Prop_shadowOffsetX ) ); + rManager.ScaleEmu( nVal ); + if ( nVal ) + rSet.Put( SdrShadowXDistItem( nVal ) ); + } + if ( IsProperty( DFF_Prop_shadowOffsetY ) ) + { + sal_Int32 nVal = static_cast< sal_Int32 >( GetPropertyValue( DFF_Prop_shadowOffsetY ) ); + rManager.ScaleEmu( nVal ); + if ( nVal ) + rSet.Put( SdrShadowYDistItem( nVal ) ); + } + if ( IsProperty( DFF_Prop_fshadowObscured ) ) + { + bHasShadow = ( GetPropertyValue( DFF_Prop_fshadowObscured ) & 2 ) != 0; + if ( bHasShadow ) + { + if ( !IsProperty( DFF_Prop_shadowOffsetX ) ) + rSet.Put( SdrShadowXDistItem( 35 ) ); + if ( !IsProperty( DFF_Prop_shadowOffsetY ) ) + rSet.Put( SdrShadowYDistItem( 35 ) ); } } - if ( bHasShadow ) { // #160376# sj: activating shadow only if fill and or linestyle is used @@ -3018,6 +2677,105 @@ void DffPropertyReader::ApplyAttributes( SvStream& rIn, SfxItemSet& rSet, const { ApplyCustomShapeGeometryAttributes( rIn, rSet, rObjData ); ApplyCustomShapeTextAttributes( rSet ); + if ( rManager.GetSvxMSDffSettings() & SVXMSDFF_SETTINGS_IMPORT_EXCEL ) + { + if ( mnFix16Angle || ( rObjData.nSpFlags & SP_FFLIPV ) ) + CheckAndCorrectExcelTextRotation( rIn, rSet, rObjData ); + } + } +} + +void DffPropertyReader::CheckAndCorrectExcelTextRotation( SvStream& rIn, SfxItemSet& rSet, DffObjData& rObjData ) const +{ + sal_Bool bRotateTextWithShape = rObjData.bRotateTextWithShape; + if ( rObjData.bOpt2 ) // sj: #158494# is the second property set available ? if then we have to check the xml data of + { // the shape, because the textrotation of Excel 2003 and greater versions is stored there + // (upright property of the textbox) + if ( rManager.pSecPropSet->SeekToContent( DFF_Prop_metroBlob, rIn ) ) + { + sal_uInt32 nLen = rManager.pSecPropSet->GetPropertyValue( DFF_Prop_metroBlob ); + if ( nLen ) + { + ::com::sun::star::uno::Sequence< sal_Int8 > aXMLDataSeq( nLen ); + rIn.Read( aXMLDataSeq.getArray(), nLen ); + ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > xInputStream + ( new ::comphelper::SequenceInputStream( aXMLDataSeq ) ); + try + { + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() ); + if ( xFactory.is() ) + { + ::com::sun::star::uno::Reference< com::sun::star::embed::XStorage > xStorage + ( ::comphelper::OStorageHelper::GetStorageOfFormatFromInputStream( + OFOPXML_STORAGE_FORMAT_STRING, xInputStream, xFactory, sal_True ) ); + if ( xStorage.is() ) + { + const rtl::OUString sDRS( RTL_CONSTASCII_USTRINGPARAM ( "drs" ) ); + ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > + xStorageDRS( xStorage->openStorageElement( sDRS, ::com::sun::star::embed::ElementModes::SEEKABLEREAD ) ); + if ( xStorageDRS.is() ) + { + const rtl::OUString sShapeXML( RTL_CONSTASCII_USTRINGPARAM ( "shapexml.xml" ) ); + ::com::sun::star::uno::Reference< ::com::sun::star::io::XStream > xShapeXMLStream( xStorageDRS->openStreamElement( sShapeXML, ::com::sun::star::embed::ElementModes::SEEKABLEREAD ) ); + if ( xShapeXMLStream.is() ) + { + ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > xShapeXMLInputStream( xShapeXMLStream->getInputStream() ); + if ( xShapeXMLInputStream.is() ) + { + ::com::sun::star::uno::Sequence< sal_Int8 > aSeq; + sal_Int32 nBytesRead = xShapeXMLInputStream->readBytes( aSeq, 0x7fffffff ); + if ( nBytesRead ) + { // for only one property I spare to use a XML parser at this point, this + // should be enhanced if needed + + bRotateTextWithShape = sal_True; // using the correct xml default + const char* pArry = reinterpret_cast< char* >( aSeq.getArray() ); + const char* pUpright = "upright="; + const char* pEnd = pArry + nBytesRead; + const char* pPtr = pArry; + while( ( pPtr + 12 ) < pEnd ) + { + if ( !memcmp( pUpright, pPtr, 8 ) ) + { + bRotateTextWithShape = ( pPtr[ 9 ] != '1' ) && ( pPtr[ 9 ] != 't' ); + break; + } + else + pPtr++; + } + } + } + } + } + } + } + } + catch( com::sun::star::uno::Exception& ) + { + } + } + } + } + if ( !bRotateTextWithShape ) + { + const com::sun::star::uno::Any* pAny, aAny; + SdrCustomShapeGeometryItem aGeometryItem((SdrCustomShapeGeometryItem&)rSet.Get( SDRATTR_CUSTOMSHAPE_GEOMETRY )); + const rtl::OUString sTextRotateAngle( RTL_CONSTASCII_USTRINGPARAM ( "TextRotateAngle" ) ); + pAny = aGeometryItem.GetPropertyValueByName( sTextRotateAngle ); + double fExtraTextRotateAngle = 0.0; + if ( pAny ) + *pAny >>= fExtraTextRotateAngle; + + if ( rManager.mnFix16Angle ) + fExtraTextRotateAngle += mnFix16Angle / 100.0; + if ( rObjData.nSpFlags & SP_FFLIPV ) + fExtraTextRotateAngle -= 180.0; + + com::sun::star::beans::PropertyValue aTextRotateAngle; + aTextRotateAngle.Name = sTextRotateAngle; + aTextRotateAngle.Value <<= fExtraTextRotateAngle; + aGeometryItem.SetPropertyValue( aTextRotateAngle ); + rSet.Put( aGeometryItem ); } } @@ -3374,7 +3132,7 @@ sal_Bool SvxMSDffManager::SeekToShape( SvStream& rSt, void* /* pClientData */, s bool SvxMSDffManager::SeekToRec( SvStream& rSt, sal_uInt16 nRecId, sal_uLong nMaxFilePos, DffRecordHeader* pRecHd, sal_uLong nSkipCount ) const { bool bRet = sal_False; - sal_uLong nFPosMerk = rSt.Tell(); // FilePos merken fuer ggf. spaetere Restauration + sal_uLong nFPosMerk = rSt.Tell(); // store FilePos to restore it later if necessary DffRecordHeader aHd; do { @@ -3405,7 +3163,7 @@ bool SvxMSDffManager::SeekToRec( SvStream& rSt, sal_uInt16 nRecId, sal_uLong nMa } while ( rSt.good() && rSt.Tell() < nMaxFilePos && !bRet ); if ( !bRet ) - rSt.Seek( nFPosMerk ); // restore FilePos + rSt.Seek( nFPosMerk ); // restore original FilePos return bRet; } @@ -3433,7 +3191,7 @@ bool SvxMSDffManager::SeekToRec2( sal_uInt16 nRecId1, sal_uInt16 nRecId2, sal_uL if ( !bRet ) aHd.SeekToEndOfRecord( rStCtrl ); } - while ( rStCtrl.GetError() == 0 && rStCtrl.Tell() < nMaxFilePos && !bRet ); + while ( rStCtrl.good() && rStCtrl.Tell() < nMaxFilePos && !bRet ); if ( !bRet ) rStCtrl.Seek( nFPosMerk ); // restore FilePos return bRet; @@ -3697,32 +3455,6 @@ Color SvxMSDffManager::MSO_CLR_ToColor( sal_uInt32 nColorCode, sal_uInt16 nConte return aColor; } -rtl::OUString SvxMSDffManager::ReadDffString(SvStream& rSt, DffRecordHeader aStrHd) -{ - String aRet; - if( aStrHd.nRecType == 0x0 && !ReadCommonRecordHeader(aStrHd, rSt) ) - rSt.Seek( aStrHd.nFilePos ); - else if ( aStrHd.nRecType == DFF_PST_TextBytesAtom || aStrHd.nRecType == DFF_PST_TextCharsAtom ) - { - bool bUniCode=aStrHd.nRecType==DFF_PST_TextCharsAtom; - sal_uInt32 nBytes = aStrHd.nRecLen; - aRet = MSDFFReadZString( rSt, nBytes, bUniCode ); - if( !bUniCode ) - { - for ( xub_StrLen n = 0; n < nBytes; n++ ) - { - if( aRet.GetChar( n ) == 0x0B ) - aRet.SetChar( n, ' ' ); // Weicher Umbruch - // TODO: Zeilenumbruch im Absatz via Outliner setzen. - } - } - aStrHd.SeekToEndOfRecord( rSt ); - } - else - aStrHd.SeekToBegOfRecord( rSt ); - return aRet; -} - // sj: I just want to set a string for a text object that may contain multiple // paragraphs. If I now take a look at the follwing code I get the impression that // our outliner is too complicate to be used properly, @@ -3786,185 +3518,6 @@ void SvxMSDffManager::ReadObjText( const String& rText, SdrObject* pObj ) const } } -bool SvxMSDffManager::ReadObjText(SvStream& rSt, SdrObject* pObj) -{ - bool bRet=sal_False; - SdrTextObj* pText = PTR_CAST(SdrTextObj, pObj); - if( pText ) - { - DffRecordHeader aTextHd; - if( !ReadCommonRecordHeader(aTextHd, rSt) ) - rSt.Seek( aTextHd.nFilePos ); - else if ( aTextHd.nRecType==DFF_msofbtClientTextbox || aTextHd.nRecType == 0x1022 ) - { - bRet=sal_True; - sal_uLong nRecEnd=aTextHd.GetRecEndFilePos(); - DffRecordHeader aHd; - String aText; - - SdrOutliner& rOutliner=pText->ImpGetDrawOutliner(); - sal_uInt16 nOutlMode = rOutliner.GetMode(); - - { // apparently a small bug in the EditEngine which causes - // the paragraph attributes not to be delted on Clear() - bool bClearParaAttribs = true; - rOutliner.SetStyleSheet( 0, NULL ); - SfxItemSet aSet(rOutliner.GetEmptyItemSet()); - aSet.Put(SvxColorItem( COL_BLACK )); - rOutliner.SetParaAttribs(0,aSet); - pText->SetMergedItemSet(aSet); - - bClearParaAttribs = sal_False; - if( bClearParaAttribs ) - { - // apparently a small bug in the EditEngine which causes - // the paragraph attributes not to be delted on Clear() - rOutliner.SetParaAttribs(0,rOutliner.GetEmptyItemSet()); - } - } - rOutliner.Init( OUTLINERMODE_TEXTOBJECT ); - - /////////////////////////////////// - // read TextString and MetaChars // - /////////////////////////////////// - do - { - if( !ReadCommonRecordHeader(aHd, rSt) ) - rSt.Seek( aHd.nFilePos ); - else - { - switch (aHd.nRecType) - { - default: - break; - //case DFF_PST_TextHeaderAtom: - //case TextSpecInfoAtom - case DFF_PST_TextBytesAtom: - case DFF_PST_TextCharsAtom: - aText = ReadDffString(rSt, aHd); - break; - case DFF_PST_TextRulerAtom : - { - sal_uInt16 nLen = (sal_uInt16)aHd.nRecLen; - if(nLen) - { - sal_uInt32 nMask; - sal_uInt16 nVal1, nVal2, nVal3; - sal_uInt16 nDefaultTab = 2540; // PPT def: 1 Inch //rOutliner.GetDefTab(); - sal_uInt16 nMostrightTab = 0; - SfxItemSet aSet(rOutliner.GetEmptyItemSet()); - SvxTabStopItem aTabItem(0, 0, SVX_TAB_ADJUST_DEFAULT, EE_PARA_TABS); - - rSt >> nMask; - nLen -= 4; - - if(nLen && (nMask & 0x0002)) - { - // number of indent levels - rSt >> nVal3; - nLen -= 2; - } - - // Allg. TAB verstellt auf Wert in nVal3 - if(nLen && (nMask & 0x0001)) - { - rSt >> nVal3; - nLen -= 2; - nDefaultTab = (sal_uInt16)(((sal_uInt32)nVal3 * 1000) / 240); - } - - // Weitere, frei gesetzte TABs - if(nLen && (nMask & 0x0004)) - { - rSt >> nVal1; - nLen -= 2; - - // fest gesetzte TABs importieren - while(nLen && nVal1--) - { - rSt >> nVal2; - rSt >> nVal3; - nLen -= 4; - - sal_uInt16 nNewTabPos = (sal_uInt16)(((sal_uInt32)nVal2 * 1000) / 240); - if(nNewTabPos > nMostrightTab) - nMostrightTab = nNewTabPos; - - SvxTabStop aTabStop(nNewTabPos); - aTabItem.Insert(aTabStop); - } - } - - // evtl. noch default-TABs ergaenzen (immer) - sal_uInt16 nObjWidth = sal_uInt16(pObj->GetSnapRect().GetWidth() + 1); - sal_uInt16 nDefaultTabPos = nDefaultTab; - - while(nDefaultTabPos <= nObjWidth && nDefaultTabPos <= nMostrightTab) - nDefaultTabPos = - nDefaultTabPos + nDefaultTab; - - while(nDefaultTabPos <= nObjWidth) - { - SvxTabStop aTabStop(nDefaultTabPos); - aTabItem.Insert(aTabStop); - nDefaultTabPos = - nDefaultTabPos + nDefaultTab; - } - - // Falls TABs angelegt wurden, setze diese - if(aTabItem.Count()) - { - aSet.Put(aTabItem); - rOutliner.SetParaAttribs(0, aSet); - } - } - } - break; - } - aHd.SeekToEndOfRecord( rSt ); - } - } - while ( rSt.GetError() == 0 && rSt.Tell() < nRecEnd ); - - //////////////////////// - // replace SHIFT-Ret // - //////////////////////// - if ( aText.Len() ) - { - aText += ' '; - aText.SetChar( aText.Len()-1, 0x0D ); - rOutliner.SetText( aText, rOutliner.GetParagraph( 0 ) ); - - // replace SHIFT-Ret in the Outliner - if (comphelper::string::getTokenCount(aText, 0x0B) > 1) - { - sal_uInt32 nParaCount = rOutliner.GetParagraphCount(); - for(sal_uInt16 a=0;a<nParaCount;a++) - { - Paragraph* pActPara = rOutliner.GetParagraph(a); - String aParaText = rOutliner.GetText(pActPara); - for(sal_uInt16 b=0;b<aParaText.Len();b++) - { - if( aParaText.GetChar( b ) == 0x0B) - { - ESelection aSelection(a, b, a, b+1); - rOutliner.QuickInsertLineBreak(aSelection); - } - } - } - } - } - OutlinerParaObject* pNewText=rOutliner.CreateParaObject(); - rOutliner.Init( nOutlMode ); - pText->NbcSetOutlinerParaObject(pNewText); - } - else - aTextHd.SeekToBegOfRecord(rSt); - - } - return bRet; -} - //static rtl::OUString SvxMSDffManager::MSDFFReadZString(SvStream& rIn, sal_uInt32 nLen, bool bUniCode) @@ -4442,6 +3995,7 @@ SdrObject* SvxMSDffManager::ImportShape( const DffRecordHeader& rHd, SvStream& r return pRet; DffObjData aObjData( rHd, rClientRect, nCalledByGroup ); + aObjData.bRotateTextWithShape = ( GetSvxMSDffSettings() & SVXMSDFF_SETTINGS_IMPORT_EXCEL ) == 0; maShapeRecords.Consume( rSt, sal_False ); aObjData.bShapeType = maShapeRecords.SeekToContent( rSt, DFF_msofbtSp, SEEK_FROM_BEGINNING ); if ( aObjData.bShapeType ) @@ -4473,10 +4027,18 @@ SdrObject* SvxMSDffManager::ImportShape( const DffRecordHeader& rHd, SvStream& r } else { - InitializePropSet(); // get the default PropSet + InitializePropSet( DFF_msofbtOPT ); // get the default PropSet ( (DffPropertyReader*) this )->mnFix16Angle = 0; } + aObjData.bOpt2 = maShapeRecords.SeekToContent( rSt, DFF_msofbtUDefProp, SEEK_FROM_CURRENT_AND_RESTART ); + if ( aObjData.bOpt2 ) + { + maShapeRecords.Current()->SeekToBegOfRecord( rSt ); + pSecPropSet = new DffPropertyReader( *this ); + pSecPropSet->ReadPropSet( rSt, NULL ); + } + aObjData.bChildAnchor = maShapeRecords.SeekToContent( rSt, DFF_msofbtChildAnchor, SEEK_FROM_CURRENT_AND_RESTART ); if ( aObjData.bChildAnchor ) { @@ -5756,6 +5318,7 @@ SvxMSDffManager::SvxMSDffManager(SvStream& rStCtrl_, pStData2( pStData2_ ), nSvxMSDffSettings( 0 ), nSvxMSDffOLEConvFlags( 0 ), + pSecPropSet( NULL ), mnDefaultColor( mnDefaultColor_), mbTracing( sal_False ) { @@ -5800,6 +5363,7 @@ SvxMSDffManager::SvxMSDffManager( SvStream& rStCtrl_, const String& rBaseURL ) pStData2( 0 ), nSvxMSDffSettings( 0 ), nSvxMSDffOLEConvFlags( 0 ), + pSecPropSet( NULL ), mnDefaultColor( COL_DEFAULT ), mbTracing( sal_False ) { @@ -5808,6 +5372,7 @@ SvxMSDffManager::SvxMSDffManager( SvStream& rStCtrl_, const String& rBaseURL ) SvxMSDffManager::~SvxMSDffManager() { + delete pSecPropSet; delete pBLIPInfos; delete pShapeOrders; delete pFormModel; @@ -6009,7 +5574,7 @@ void SvxMSDffManager::GetCtrlData( sal_uInt32 nOffsDgg_ ) if( !bOk ) { - nPos++; + nPos++; // ????????? TODO: trying to get an one-hit wonder, this code code should be rewritten... if (nPos != rStCtrl.Seek(nPos)) break; bOk = ReadCommonRecordHeader( rStCtrl, nVer, nInst, nFbt, nLength ) @@ -6022,7 +5587,7 @@ void SvxMSDffManager::GetCtrlData( sal_uInt32 nOffsDgg_ ) nPos += DFF_COMMON_RECORD_HEADER_SIZE + nLength; ++nDrawingContainerId; } - while( nPos < nMaxStrPos && bOk ); + while( ( rStCtrl.GetError() == 0 ) && ( nPos < nMaxStrPos ) && bOk ); } } |