Files
loongoffice/xmloff/source/draw/XMLShapeStyleContext.cxx
Caolán McNamara 5aa360cae0 Resolves: fdo#80468 and fdo#81223 image/frame backgrounds wrong
writer has code to fill in missing new properties from the old properties
if they exist. But xmloff is stripping them out before they get there.

Don't strip them out, and add in a missing check for one of the
archaic bg colors and add a regression test for fdo#81223

Change-Id: I9a541a9bee0a01c90f2c33383f1144ecd8b0bfff
2014-09-29 16:31:32 +01:00

314 lines
12 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* 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/.
*
* This file incorporates work covered by the following license notice:
*
* 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 <tools/debug.hxx>
#include <xmloff/XMLShapeStyleContext.hxx>
#include "XMLShapePropertySetContext.hxx"
#include <xmloff/contextid.hxx>
#include <com/sun/star/drawing/XControlShape.hpp>
#include <com/sun/star/beans/XPropertySetInfo.hpp>
#include <com/sun/star/lang/IllegalArgumentException.hpp>
#include <com/sun/star/drawing/FillStyle.hpp>
#include <xmloff/xmlimp.hxx>
#include <xmloff/xmlnumi.hxx>
#include <xmloff/xmlnmspe.hxx>
#include <xmloff/xmltoken.hxx>
#include <xmloff/xmlerror.hxx>
#include <xmloff/maptype.hxx>
#include "sdpropls.hxx"
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::drawing;
using ::xmloff::token::IsXMLToken;
using ::xmloff::token::XML_TEXT_PROPERTIES;
using ::xmloff::token::XML_GRAPHIC_PROPERTIES;
using ::xmloff::token::XML_PARAGRAPH_PROPERTIES;
TYPEINIT1( XMLShapeStyleContext, XMLPropStyleContext );
XMLShapeStyleContext::XMLShapeStyleContext(
SvXMLImport& rImport,
sal_uInt16 nPrfx,
const OUString& rLName,
const uno::Reference< xml::sax::XAttributeList >& xAttrList,
SvXMLStylesContext& rStyles,
sal_uInt16 nFamily)
: XMLPropStyleContext(rImport, nPrfx, rLName, xAttrList, rStyles, nFamily ),
m_bIsNumRuleAlreadyConverted( false )
{
}
XMLShapeStyleContext::~XMLShapeStyleContext()
{
}
void XMLShapeStyleContext::SetAttribute( sal_uInt16 nPrefixKey, const OUString& rLocalName, const OUString& rValue )
{
if (m_sControlDataStyleName.isEmpty() && (::xmloff::token::GetXMLToken(::xmloff::token::XML_DATA_STYLE_NAME) == rLocalName))
{
m_sControlDataStyleName = rValue;
}
else if( (XML_NAMESPACE_STYLE == nPrefixKey) && IsXMLToken( rLocalName, ::xmloff::token::XML_LIST_STYLE_NAME ) )
{
m_sListStyleName = rValue;
}
else
{
XMLPropStyleContext::SetAttribute( nPrefixKey, rLocalName, rValue );
if( (XML_NAMESPACE_STYLE == nPrefixKey) &&
( IsXMLToken( rLocalName, ::xmloff::token::XML_NAME ) || IsXMLToken( rLocalName, ::xmloff::token::XML_DISPLAY_NAME ) ) )
{
if( !GetName().isEmpty() && !GetDisplayName().isEmpty() && GetName() != GetDisplayName() )
{
const_cast< SvXMLImport&>( GetImport() ).
AddStyleDisplayName( GetFamily(), GetName(), GetDisplayName() );
}
}
}
}
SvXMLImportContext *XMLShapeStyleContext::CreateChildContext(
sal_uInt16 nPrefix,
const OUString& rLocalName,
const Reference< xml::sax::XAttributeList > & xAttrList )
{
SvXMLImportContext *pContext = 0;
if( XML_NAMESPACE_STYLE == nPrefix || XML_NAMESPACE_LO_EXT == nPrefix )
{
sal_uInt32 nFamily = 0;
if( IsXMLToken( rLocalName, XML_TEXT_PROPERTIES ) )
nFamily = XML_TYPE_PROP_TEXT;
else if( IsXMLToken( rLocalName, XML_PARAGRAPH_PROPERTIES ) )
nFamily = XML_TYPE_PROP_PARAGRAPH;
else if( IsXMLToken( rLocalName, XML_GRAPHIC_PROPERTIES ) )
nFamily = XML_TYPE_PROP_GRAPHIC;
if( nFamily )
{
rtl::Reference < SvXMLImportPropertyMapper > xImpPrMap =
GetStyles()->GetImportPropertyMapper( GetFamily() );
if( xImpPrMap.is() )
pContext = new XMLShapePropertySetContext( GetImport(), nPrefix,
rLocalName, xAttrList,
nFamily,
GetProperties(),
xImpPrMap );
}
}
if( !pContext )
pContext = XMLPropStyleContext::CreateChildContext( nPrefix, rLocalName,
xAttrList );
return pContext;
}
void XMLShapeStyleContext::FillPropertySet( const Reference< beans::XPropertySet > & rPropSet )
{
if( !m_bIsNumRuleAlreadyConverted )
{
m_bIsNumRuleAlreadyConverted = true;
// for compatibility to beta files, search for CTF_SD_NUMBERINGRULES_NAME to
// import numbering rules from the style:properties element
const rtl::Reference< XMLPropertySetMapper >&rMapper = GetStyles()->GetImportPropertyMapper( GetFamily() )->getPropertySetMapper();
::std::vector< XMLPropertyState > &rProperties = GetProperties();
::std::vector< XMLPropertyState >::iterator end( rProperties.end() );
::std::vector< XMLPropertyState >::iterator property;
// first, look for the old format, where we had a text:list-style-name
// attribute in the style:properties element
for( property = rProperties.begin(); property != end; ++property )
{
// find properties with context
if( (property->mnIndex != -1) && (rMapper->GetEntryContextId( property->mnIndex ) == CTF_SD_NUMBERINGRULES_NAME) )
break;
}
// if we did not find an old list-style-name in the properties, and we need one
// because we got a style:list-style attribute in the style-style element
// we generate one
if( (property == end) && ( !m_sListStyleName.isEmpty() ) )
{
sal_Int32 nIndex = rMapper->FindEntryIndex( CTF_SD_NUMBERINGRULES_NAME );
DBG_ASSERT( -1 != nIndex, "can't find numbering rules property entry, can't set numbering rule!" );
XMLPropertyState aNewState( nIndex );
rProperties.push_back( aNewState );
end = rProperties.end();
property = end - 1;
}
// so, if we have an old or a new list style name, we set its value to
// a numbering rule
if( property != end )
{
if( m_sListStyleName.isEmpty() )
{
property->maValue >>= m_sListStyleName;
}
const SvxXMLListStyleContext *pListStyle = GetImport().GetTextImport()->FindAutoListStyle( m_sListStyleName );
DBG_ASSERT( pListStyle, "list-style not found for shape style" );
if( pListStyle )
{
uno::Reference< container::XIndexReplace > xNumRule( SvxXMLListStyleContext::CreateNumRule( GetImport().GetModel() ) );
pListStyle->FillUnoNumRule(xNumRule, NULL /* const SvI18NMap * ??? */ );
property->maValue <<= xNumRule;
}
else
{
property->mnIndex = -1;
}
}
}
struct _ContextID_Index_Pair aContextIDs[] =
{
{ CTF_DASHNAME , -1 },
{ CTF_LINESTARTNAME , -1 },
{ CTF_LINEENDNAME , -1 },
{ CTF_FILLGRADIENTNAME, -1 },
{ CTF_FILLTRANSNAME , -1 },
{ CTF_FILLHATCHNAME , -1 },
{ CTF_FILLBITMAPNAME , -1 },
{ CTF_SD_OLE_VIS_AREA_IMPORT_LEFT, -1 },
{ CTF_SD_OLE_VIS_AREA_IMPORT_TOP, -1 },
{ CTF_SD_OLE_VIS_AREA_IMPORT_WIDTH, -1 },
{ CTF_SD_OLE_VIS_AREA_IMPORT_HEIGHT, -1 },
{ -1, -1 }
};
static const sal_uInt16 aFamilies[] =
{
XML_STYLE_FAMILY_SD_STROKE_DASH_ID,
XML_STYLE_FAMILY_SD_MARKER_ID,
XML_STYLE_FAMILY_SD_MARKER_ID,
XML_STYLE_FAMILY_SD_GRADIENT_ID,
XML_STYLE_FAMILY_SD_GRADIENT_ID,
XML_STYLE_FAMILY_SD_HATCH_ID,
XML_STYLE_FAMILY_SD_FILL_IMAGE_ID
};
rtl::Reference < SvXMLImportPropertyMapper > xImpPrMap =
GetStyles()->GetImportPropertyMapper( GetFamily() );
DBG_ASSERT( xImpPrMap.is(), "There is the import prop mapper" );
if( xImpPrMap.is() )
xImpPrMap->FillPropertySet( GetProperties(), rPropSet, aContextIDs );
Reference< XPropertySetInfo > xInfo;
// get property set mapper
rtl::Reference<XMLPropertySetMapper> xPropMapper( xImpPrMap->getPropertySetMapper() );
for( sal_uInt16 i=0; aContextIDs[i].nContextID != -1; i++ )
{
sal_Int32 nIndex = aContextIDs[i].nIndex;
if( nIndex != -1 ) switch( aContextIDs[i].nContextID )
{
case CTF_DASHNAME:
case CTF_LINESTARTNAME:
case CTF_LINEENDNAME:
case CTF_FILLGRADIENTNAME:
case CTF_FILLTRANSNAME:
case CTF_FILLHATCHNAME:
case CTF_FILLBITMAPNAME:
{
struct XMLPropertyState& rState = GetProperties()[nIndex];
OUString sStyleName;
rState.maValue >>= sStyleName;
sStyleName = GetImport().GetStyleDisplayName( aFamilies[i], sStyleName );
try
{
// set property
const OUString& rPropertyName = xPropMapper->GetEntryAPIName(rState.mnIndex);
if( !xInfo.is() )
xInfo = rPropSet->getPropertySetInfo();
if ( xInfo->hasPropertyByName( rPropertyName ) )
{
rPropSet->setPropertyValue( rPropertyName, Any( sStyleName ) );
}
}
catch ( const ::com::sun::star::lang::IllegalArgumentException& e )
{
Sequence<OUString> aSeq(1);
aSeq[0] = sStyleName;
GetImport().SetError(
XMLERROR_STYLE_PROP_VALUE | XMLERROR_FLAG_WARNING,
aSeq, e.Message, NULL );
}
break;
}
case CTF_SD_OLE_VIS_AREA_IMPORT_LEFT:
case CTF_SD_OLE_VIS_AREA_IMPORT_TOP:
case CTF_SD_OLE_VIS_AREA_IMPORT_WIDTH:
case CTF_SD_OLE_VIS_AREA_IMPORT_HEIGHT:
{
struct XMLPropertyState& rState = GetProperties()[nIndex];
const OUString& rPropertyName = xPropMapper->GetEntryAPIName(rState.mnIndex);
try
{
if( !xInfo.is() )
xInfo = rPropSet->getPropertySetInfo();
if ( xInfo->hasPropertyByName( rPropertyName ) )
{
rPropSet->setPropertyValue( rPropertyName, rState.maValue );
}
}
catch ( const ::com::sun::star::lang::IllegalArgumentException& e )
{
Sequence<OUString> aSeq;
GetImport().SetError(
XMLERROR_STYLE_PROP_VALUE | XMLERROR_FLAG_WARNING,
aSeq, e.Message, NULL );
}
break;
}
}
}
if (!m_sControlDataStyleName.isEmpty())
{ // we had a data-style-name attribute
// set the formatting on the control model of the control shape
uno::Reference< drawing::XControlShape > xControlShape(rPropSet, uno::UNO_QUERY);
DBG_ASSERT(xControlShape.is(), "XMLShapeStyleContext::FillPropertySet: data style for a non-control shape!");
if (xControlShape.is())
{
uno::Reference< beans::XPropertySet > xControlModel(xControlShape->getControl(), uno::UNO_QUERY);
DBG_ASSERT(xControlModel.is(), "XMLShapeStyleContext::FillPropertySet: no control model for the shape!");
if (xControlModel.is())
{
GetImport().GetFormImport()->applyControlNumberStyle(xControlModel, m_sControlDataStyleName);
}
}
}
}
void XMLShapeStyleContext::Finish( bool /*bOverwrite*/ )
{
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */