filter/source/svg/presentation_engine.js | 141 ++++++++++++------------------- filter/source/svg/svgexport.cxx | 12 +- filter/source/svg/svgwriter.cxx | 42 +++------ sd/qa/unit/SVGExportTests.cxx | 18 +-- 4 files changed, 88 insertions(+), 125 deletions(-)
New commits: commit 5a30e56b51b1d14151859e2f710fe822156d287c Author: Marco Cecchetti <marco.cecche...@collabora.com> AuthorDate: Mon Nov 21 16:43:34 2022 +0100 Commit: Andras Timar <andras.ti...@collabora.com> CommitDate: Mon Nov 21 20:54:35 2022 +0100 svg export filter: text fields not handled correctly New solution for fixing text field issues: - small text field are not substituted with the right content because the placeholder text span several lines - copy of standard text fields embedded in the default master page are not substitute with the right content. Change-Id: Ifc8773f1ba41f9d0fe6f6ef3982cb64a514fcec7 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143045 Reviewed-by: Andras Timar <andras.ti...@collabora.com> Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js index 08ca59498dfe..def2e947ad36 100644 --- a/filter/source/svg/presentation_engine.js +++ b/filter/source/svg/presentation_engine.js @@ -4464,13 +4464,13 @@ var aOOOAttrTextAdjust = 'text-adjust'; // element class names var aClipPathGroupClassName = 'ClipPathGroup'; var aPageClassName = 'Page'; -var aSlideNumberClassName = 'Slide_Number'; -var aDateTimeClassName = 'Date/Time'; +var aSlideNumberClassName = 'PageNumber'; +var aDateTimeClassName = 'DateTime'; var aFooterClassName = 'Footer'; var aHeaderClassName = 'Header'; var aDateClassName = 'Date'; var aTimeClassName = 'Time'; -var aSlideNameClassName='SlideName'; +var aSlideNameClassName='PageName'; // Creating a namespace dictionary. var NSS = {}; @@ -4785,15 +4785,6 @@ function getRandomInt( nMax ) return Math.floor( Math.random() * nMax ); } -function isTextFieldElement( aElement ) // eslint-disable-line no-unused-vars -{ - var sClassName = aElement.getAttribute( 'class' ); - return ( sClassName === aSlideNumberClassName ) || - ( sClassName === aFooterClassName ) || - ( sClassName === aHeaderClassName ) || - ( sClassName === aDateTimeClassName ); -} - /********************* ** Debug Utilities ** @@ -5192,10 +5183,11 @@ initPlaceholderElements : function() for( ; i < aPlaceholderList.length; ++i ) { var aPlaceholderElem = aPlaceholderList[i]; - var sContent = aPlaceholderElem.textContent; - if( sContent === '<date>' ) + var sClass = aPlaceholderElem.getAttribute('class'); + var sFieldType = sClass.split(' ')[1]; + if( sFieldType === aDateClassName) aPlaceholderElem.textContent = new Date().toLocaleDateString(); - else if( sContent === '<time>' ) + else if( sFieldType === aTimeClassName ) aPlaceholderElem.textContent = new Date().toLocaleTimeString(); } }, @@ -5376,53 +5368,43 @@ getSlideAnimationsRoot : function() }; // end MetaSlide prototype -function getTextFieldType ( elem ) +function removeRedundantParagraphFromTextFieldShape( aObject ) { - var sFieldType = null; - var sClass = elem.getAttribute('class'); - if( sClass == 'TextShape' ) + var aTextElem = getElementByClassName( aObject, 'SVGTextShape' ); + if( aTextElem ) { - var aPlaceholderElement = getElementByClassName( elem, 'PlaceholderText' ); - if (aPlaceholderElement) + var aPlaceholderElement = getElementsByClassName(aTextElem, 'PlaceholderText'); + if( aPlaceholderElement ) { - var sContent = aPlaceholderElement.textContent - if (sContent === '<number>') - sFieldType = aSlideNumberClassName; - else if (sContent === '<date/time>') - sFieldType = aDateTimeClassName; - else if (sContent === '<date>') - sFieldType = aDateClassName; - else if (sContent === '<time>') - sFieldType = aTimeClassName; - else if (sContent === '<slide-name>') - sFieldType = aSlideNameClassName; - else if (sContent === '<footer>') - sFieldType = aFooterClassName; - else if (sContent === '<header>') - sFieldType = aHeaderClassName; + var aTextParagraphSet = getElementsByClassName(aTextElem, 'TextParagraph'); + // When the text field width is too small, the placeholder text spans several lines. + // We remove all text lines but the first one which is used as a placeholder. + // This is a workaround but it should work in the majority of cases. + // A complete solution needs to support svg text wrapping. + if( aTextParagraphSet.length > 1 ) + { + var i = aTextParagraphSet.length; + while( i > 1 ) + { + aTextElem.removeChild(aTextParagraphSet[i - 1]); + --i; + } + } } + } +} - if( sFieldType ) - return sFieldType; - - var aTextPortionElement = getElementByClassName( elem, 'TextPortion' ); - if( aTextPortionElement ) +function getTextFieldType ( elem ) { + var sFieldType = null; + var sClass = elem.getAttribute('class'); + if( sClass === 'TextShape' ) + { + var aPlaceholderElement = getElementByClassName(elem, 'PlaceholderText'); + if( aPlaceholderElement ) { - var sContent = aTextPortionElement.textContent - if( sContent.indexOf( '<number>' ) != -1 ) - sFieldType = aSlideNumberClassName; - else if( sContent.indexOf( '<date/time>' ) != -1 ) - sFieldType = aDateTimeClassName; - else if( sContent.indexOf( '<date>' ) != -1 ) - sFieldType = aDateClassName; - else if( sContent.indexOf( '<time>' ) != -1 ) - sFieldType = aTimeClassName; - else if( sContent.indexOf( '<slide-name>' ) != -1 ) - sFieldType = aSlideNameClassName; - else if( sContent.indexOf( '<footer>' ) != -1 ) - sFieldType = aFooterClassName; - else if( sContent.indexOf( '<header>' ) != -1 ) - sFieldType = aHeaderClassName; + var sClassAttr = aPlaceholderElement.getAttribute('class'); + var classes = sClassAttr.split(' '); + sFieldType = classes[1]; } } return sFieldType; @@ -5450,7 +5432,7 @@ function isTextFieldByClassName ( sClassName ) * background image * </g> * <g class='BackgroundObjects'> - * <g class='Date/Time'> + * <g class='DateTime'> * date/time placeholder * </g> * <g class='Header'> @@ -5459,7 +5441,7 @@ function isTextFieldByClassName ( sClassName ) * <g class='Footer'> * footer placeholder * </g> - * <g class='Slide_Number'> + * <g class='PageNumber'> * slide number placeholder * </g> * shapes @@ -5516,6 +5498,7 @@ function MasterPage( sMasterPageId, aMetaSlide ) for( ; i < aBackgroundObjectList.length; ++i ) { var aObject = aBackgroundObjectList[i]; + removeRedundantParagraphFromTextFieldShape( aObject ); sClass = null; var sFieldType = getTextFieldType( aObject ); if( sFieldType && aObject.firstElementChild ) @@ -5530,6 +5513,12 @@ function MasterPage( sMasterPageId, aMetaSlide ) if( !sClass ) { sClass = aBackgroundObjectList[i].getAttribute('class'); + if( sClass === aDateTimeClassName || sClass === aFooterClassName + || sClass === aHeaderClassName || sClass === aSlideNumberClassName) + { + sClass += '.Default'; + aObject.setAttribute('class', sClass); + } } if( !sClass || !isTextFieldByClassName( sClass ) ) { @@ -5633,20 +5622,6 @@ PlaceholderShape.prototype.init = function() var aTextElem = getElementByClassName( aTextFieldElement, 'SVGTextShape' ); if( aTextElem ) { - var aTextParagraphSet = getElementsByClassName( aTextElem, 'TextParagraph' ); - // When the text field width is too small, the placeholder text spans several lines. - // We remove all text lines but the first one which is used as a placeholder. - // This is a workaround but it should work in the majority of cases. - // A complete solution needs to support svg text wrapping. - if( aTextParagraphSet.length > 1 ) - { - var i = aTextParagraphSet.length; - while( i > 1 ) - { - aTextElem.removeChild(aTextParagraphSet[i-1]); - --i; - } - } var aPlaceholderElement = getElementByClassName(aTextElem, 'PlaceholderText'); if( aPlaceholderElement ) { @@ -5750,10 +5725,10 @@ PlaceholderShape.prototype.init = function() * <use class='Background'> // reference to master page background element * <g class='BackgroundObjects'> * <use class='BackgroundObjectSubGroup'> // reference to the group of shapes on the master page that are below text fields - * <g class='Slide_Number'> // a cloned element + * <g class='PageNumber'> // a cloned element * ... * </g> - * <use class='Date/Time'> // reference to a clone + * <use class='DateTime'> // reference to a clone * <use class='Footer'> * <use class='Header'> * <use class='BackgroundObjectSubGroup'> // reference to the group of shapes on the master page that are above text fields @@ -5877,7 +5852,7 @@ MasterPageView.prototype.createElement = function() // The cloned element is appended directly to the field group element // since there is no slide number field content shared between two slide // (because the slide number of two slide is always different). - var nIsPageNumberVisible = sId === aSlideNumberClassName ? this.aMetaSlide.nIsPageNumberVisible : true; + var nIsPageNumberVisible = sId === (aSlideNumberClassName + '.Default') ? this.aMetaSlide.nIsPageNumberVisible : true; if( aPlaceholderShapeSet[sId] && aPlaceholderShapeSet[sId].isValid() && nIsPageNumberVisible && @@ -5888,39 +5863,39 @@ MasterPageView.prototype.createElement = function() aTextFieldContentProviderSet[aSlideNumberClassName] ); aSlideNumberFieldHandler.update( this.aMetaSlide.nSlideNumber ); aSlideNumberFieldHandler.appendTo( this.aBackgroundObjectsElement ); - if ( sId === aSlideNumberClassName ) + if ( sId === aSlideNumberClassName + '.Default' ) this.aSlideNumberFieldHandler = aSlideNumberFieldHandler; } } - else if( sId === aDateTimeClassName ) + else if( sId === aDateTimeClassName + '.Default' ) { - // Date/Time field + // DateTime field if( this.aMetaSlide.nIsDateTimeVisible ) { this.aDateTimeFieldHandler = - this.initTextFieldHandler( aDateTimeClassName, aPlaceholderShapeSet, + this.initTextFieldHandler( sId, aPlaceholderShapeSet, aTextFieldContentProviderSet, aDefsElement, aTextFieldHandlerSet, sMasterSlideId ); } } - else if( sId === aFooterClassName ) + else if( sId === aFooterClassName + '.Default' ) { // Footer Field if( this.aMetaSlide.nIsFooterVisible ) { this.aFooterFieldHandler = - this.initTextFieldHandler( aFooterClassName, aPlaceholderShapeSet, + this.initTextFieldHandler( sId, aPlaceholderShapeSet, aTextFieldContentProviderSet, aDefsElement, aTextFieldHandlerSet, sMasterSlideId ); } } - else if( sId === aHeaderClassName ) + else if( sId === aHeaderClassName + '.Default' ) { // Header Field if( this.aMetaSlide.nIsHeaderVisible ) { this.aHeaderFieldHandler = - this.initTextFieldHandler( aHeaderClassName, aPlaceholderShapeSet, + this.initTextFieldHandler( sId, aPlaceholderShapeSet, aTextFieldContentProviderSet, aDefsElement, aTextFieldHandlerSet, sMasterSlideId ); } diff --git a/filter/source/svg/svgexport.cxx b/filter/source/svg/svgexport.cxx index ef7c0fda1935..ae74a6e2fbc6 100644 --- a/filter/source/svg/svgexport.cxx +++ b/filter/source/svg/svgexport.cxx @@ -1286,7 +1286,7 @@ void SVGFilter::implGenerateMetaData() if( !bBackgroundVisibility ) // visibility default value: 'visible' mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrBackgroundVisibility, "hidden" ); - // Page Number, Date/Time, Footer and Header Fields are regarded as background objects. + // Page Number, DateTime, Footer and Header Fields are regarded as background objects. // So bBackgroundObjectsVisibility overrides visibility of master page text fields. xPropSet->getPropertyValue( "IsBackgroundObjectsVisible" ) >>= bBackgroundObjectsVisibility; if( bBackgroundObjectsVisibility ) // visibility default value: 'visible' @@ -1303,7 +1303,7 @@ void SVGFilter::implGenerateMetaData() mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "page-number-visibility", "visible" ); } - // Date/Time Field + // DateTime Field bool bDateTimeFixed = true; // default: fixed xPropSet->getPropertyValue( "IsDateTimeFixed" ) >>= bDateTimeFixed; if( bDateTimeFixed ) // we are interested only in the field text not in the date/time format @@ -2118,9 +2118,9 @@ bool SVGFilter::implExportShape( const Reference< css::drawing::XShape >& rxShap if( mbPresentation ) { - bool bIsPageNumber = ( aShapeClass == "Slide_Number" ); + bool bIsPageNumber = ( aShapeClass == "PageNumber" ); bool bIsFooter = ( aShapeClass == "Footer" ); - bool bIsDateTime = ( aShapeClass == "Date/Time" ); + bool bIsDateTime = ( aShapeClass == "DateTime" ); bool bTextField = bIsPageNumber || bIsFooter || bIsDateTime; if( bTextField ) { @@ -2596,9 +2596,9 @@ OUString SVGFilter::implGetClassFromShape( const Reference< css::drawing::XShape else if( aShapeType.lastIndexOf( "presentation.FooterShape" ) != -1 ) aRet = "Footer"; else if( aShapeType.lastIndexOf( "presentation.DateTimeShape" ) != -1 ) - aRet = "Date/Time"; + aRet = "DateTime"; else if( aShapeType.lastIndexOf( "presentation.SlideNumberShape" ) != -1 ) - aRet = "Slide_Number"; + aRet = "PageNumber"; else if( aShapeType.lastIndexOf( "presentation.TitleTextShape" ) != -1 ) aRet = "TitleText"; else if( aShapeType.lastIndexOf( "presentation.OutlinerShape" ) != -1 ) diff --git a/filter/source/svg/svgwriter.cxx b/filter/source/svg/svgwriter.cxx index 1cb2076f4480..f8578e585b43 100644 --- a/filter/source/svg/svgwriter.cxx +++ b/filter/source/svg/svgwriter.cxx @@ -1192,7 +1192,7 @@ bool SVGTextWriter::nextTextPortion() sInfo += "text field type: " + sFieldName + "; content: " + xTextField->getPresentation( /* show command: */ false ) + "; "; #endif // This case handle Date or Time text field inserted by the user - // on both page/master page. It doesn't handle the standard Date/Time field. + // on both page/master page. It doesn't handle the standard DateTime field. if( sFieldName == "DateTime" ) { Reference<XPropertySet> xTextFieldPropSet(xTextField, UNO_QUERY); @@ -1201,7 +1201,7 @@ bool SVGTextWriter::nextTextPortion() Reference<XPropertySetInfo> xPropSetInfo = xTextFieldPropSet->getPropertySetInfo(); if( xPropSetInfo.is() ) { - // The standard Date/Time field has no property. + // The standard DateTime field has no property. // Trying to get a property value on such field would cause a runtime exception. // So the hasPropertyByName check is needed. bool bIsFixed = true; @@ -1210,7 +1210,7 @@ bool SVGTextWriter::nextTextPortion() bool bIsDate = true; if( xPropSetInfo->hasPropertyByName("IsDate") && ( ( xTextFieldPropSet->getPropertyValue( "IsDate" ) ) >>= bIsDate ) ) { - msDateTimeType = OUString::createFromAscii( bIsDate ? "<date>" : "<time>" ); + msDateTimeType = OUString::createFromAscii( bIsDate ? "Date" : "Time" ); } } } @@ -1743,9 +1743,23 @@ void SVGTextWriter::implWriteTextPortion( const Point& rPos, mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", rTextPortionId ); } + if( mbIsPlaceholderShape ) { - mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "PlaceholderText" ); + OUString sClass = "PlaceholderText"; + // This case handle Date or Time text field inserted by the user + // on both page/master page. It doesn't handle the standard DateTime field. + if( !msDateTimeType.isEmpty() ) + { + sClass += " "; + sClass += msDateTimeType; + } + else if( !msTextFieldType.isEmpty() ) + { + sClass += " "; + sClass += msTextFieldType; + } + mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", sClass ); } addFontAttributes( /* isTexTContainer: */ false ); @@ -1776,26 +1790,6 @@ void SVGTextWriter::implWriteTextPortion( const Point& rPos, SvXMLElementExport aSVGTspanElem( mrExport, XML_NAMESPACE_NONE, aXMLElemTspan, mbIWS, mbIWS ); mrExport.GetDocHandler()->characters( msPageCount ); } - // This case handle Date or Time text field inserted by the user - // on both page/master page. It doesn't handle the standard Date/Time field. - else if ( !msDateTimeType.isEmpty() ) - { - SvXMLElementExport aSVGTspanElem( mrExport, XML_NAMESPACE_NONE, aXMLElemTspan, mbIWS, mbIWS ); - mrExport.GetDocHandler()->characters( msDateTimeType ); - } - else if( mbIsPlaceholderShape && rText.startsWith("<") && rText.endsWith(">") ) - { - OUString sContent; - if( msTextFieldType == "PageNumber" ) - sContent = "<number>"; - else if( msTextFieldType == "PageName" ) - sContent = "<slide-name>"; - else - sContent = rText; - - SvXMLElementExport aSVGTspanElem( mrExport, XML_NAMESPACE_NONE, aXMLElemTspan, mbIWS, mbIWS ); - mrExport.GetDocHandler()->characters( sContent ); - } else { // Without the following attribute Google Chrome does not render leading spaces diff --git a/sd/qa/unit/SVGExportTests.cxx b/sd/qa/unit/SVGExportTests.cxx index a28e61373053..15ebe69a0df8 100644 --- a/sd/qa/unit/SVGExportTests.cxx +++ b/sd/qa/unit/SVGExportTests.cxx @@ -209,20 +209,16 @@ public: assertXPath(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_DEFS[9]/SVG_G[2]/SVG_G[2] ), "class", "BackgroundObjects"); // Current Date Field assertXPath(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_DEFS[9]/SVG_G[2]/SVG_G[2]/SVG_G[4] ), "class", "TextShape"); - assertXPath(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_DEFS[9]/SVG_G[2]/SVG_G[2]/SVG_G[4]/SVG_G/SVG_TEXT/SVG_TSPAN/SVG_TSPAN/SVG_TSPAN ), "class", "PlaceholderText"); - assertXPathContent(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_DEFS[9]/SVG_G[2]/SVG_G[2]/SVG_G[4]/SVG_G/SVG_TEXT/SVG_TSPAN/SVG_TSPAN/SVG_TSPAN ), "<date>"); + assertXPath(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_DEFS[9]/SVG_G[2]/SVG_G[2]/SVG_G[4]/SVG_G/SVG_TEXT/SVG_TSPAN/SVG_TSPAN/SVG_TSPAN ), "class", "PlaceholderText Date"); // Current Time Field assertXPath(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_DEFS[9]/SVG_G[2]/SVG_G[2]/SVG_G[5] ), "class", "TextShape"); - assertXPath(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_DEFS[9]/SVG_G[2]/SVG_G[2]/SVG_G[5]/SVG_G/SVG_TEXT/SVG_TSPAN/SVG_TSPAN/SVG_TSPAN ), "class", "PlaceholderText"); - assertXPathContent(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_DEFS[9]/SVG_G[2]/SVG_G[2]/SVG_G[5]/SVG_G/SVG_TEXT/SVG_TSPAN/SVG_TSPAN/SVG_TSPAN ), "<time>"); + assertXPath(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_DEFS[9]/SVG_G[2]/SVG_G[2]/SVG_G[5]/SVG_G/SVG_TEXT/SVG_TSPAN/SVG_TSPAN/SVG_TSPAN ), "class", "PlaceholderText Time"); // Slide Name Field assertXPath(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_DEFS[9]/SVG_G[2]/SVG_G[2]/SVG_G[6] ), "class", "TextShape"); - assertXPath(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_DEFS[9]/SVG_G[2]/SVG_G[2]/SVG_G[6]/SVG_G/SVG_TEXT/SVG_TSPAN/SVG_TSPAN/SVG_TSPAN ), "class", "PlaceholderText"); - assertXPathContent(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_DEFS[9]/SVG_G[2]/SVG_G[2]/SVG_G[6]/SVG_G/SVG_TEXT/SVG_TSPAN/SVG_TSPAN/SVG_TSPAN ), "<slide-name>"); + assertXPath(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_DEFS[9]/SVG_G[2]/SVG_G[2]/SVG_G[6]/SVG_G/SVG_TEXT/SVG_TSPAN/SVG_TSPAN/SVG_TSPAN ), "class", "PlaceholderText PageName"); // Slide Number Field assertXPath(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_DEFS[9]/SVG_G[2]/SVG_G[2]/SVG_G[7] ), "class", "TextShape"); - assertXPath(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_DEFS[9]/SVG_G[2]/SVG_G[2]/SVG_G[7]/SVG_G/SVG_TEXT/SVG_TSPAN/SVG_TSPAN/SVG_TSPAN ), "class", "PlaceholderText"); - assertXPathContent(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_DEFS[9]/SVG_G[2]/SVG_G[2]/SVG_G[7]/SVG_G/SVG_TEXT/SVG_TSPAN/SVG_TSPAN/SVG_TSPAN ), "<number>"); + assertXPath(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_DEFS[9]/SVG_G[2]/SVG_G[2]/SVG_G[7]/SVG_G/SVG_TEXT/SVG_TSPAN/SVG_TSPAN/SVG_TSPAN ), "class", "PlaceholderText PageNumber"); } void testSVGExportEmbeddedVideo() @@ -359,12 +355,10 @@ public: // Slide Name Field assertXPath(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_DEFS[9]/SVG_G[2]/SVG_G[2]/SVG_G[6] ), "class", "TextShape"); - assertXPath(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_DEFS[9]/SVG_G[2]/SVG_G[2]/SVG_G[6]/SVG_G/SVG_TEXT/SVG_TSPAN/SVG_TSPAN/SVG_TSPAN ), "class", "PlaceholderText"); - assertXPathContent(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_DEFS[9]/SVG_G[2]/SVG_G[2]/SVG_G[6]/SVG_G/SVG_TEXT/SVG_TSPAN/SVG_TSPAN/SVG_TSPAN ), "<slide-name>"); + assertXPath(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_DEFS[9]/SVG_G[2]/SVG_G[2]/SVG_G[6]/SVG_G/SVG_TEXT/SVG_TSPAN/SVG_TSPAN/SVG_TSPAN ), "class", "PlaceholderText PageName"); // Slide Number Field assertXPath(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_DEFS[9]/SVG_G[2]/SVG_G[2]/SVG_G[7] ), "class", "TextShape"); - assertXPath(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_DEFS[9]/SVG_G[2]/SVG_G[2]/SVG_G[7]/SVG_G/SVG_TEXT/SVG_TSPAN/SVG_TSPAN/SVG_TSPAN ), "class", "PlaceholderText"); - assertXPathContent(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_DEFS[9]/SVG_G[2]/SVG_G[2]/SVG_G[7]/SVG_G/SVG_TEXT/SVG_TSPAN/SVG_TSPAN/SVG_TSPAN ), "<number>"); + assertXPath(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_DEFS[9]/SVG_G[2]/SVG_G[2]/SVG_G[7]/SVG_G/SVG_TEXT/SVG_TSPAN/SVG_TSPAN/SVG_TSPAN ), "class", "PlaceholderText PageNumber"); } CPPUNIT_TEST_SUITE(SdSVGFilterTest);