1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 */ 9 10 #pragma once 11 12 #include <memory> 13 #include <string_view> 14 15 #include <test/bootstrapfixture.hxx> 16 #include <test/xmldiff.hxx> 17 #include <test/xmltesttools.hxx> 18 19 #include <unotest/filters-test.hxx> 20 #include <unotest/macros_test.hxx> 21 22 #include <drawdoc.hxx> 23 #include <DrawDocShell.hxx> 24 #include <GraphicDocShell.hxx> 25 #include <unotools/tempfile.hxx> 26 #include <unotools/ucbstreamhelper.hxx> 27 #include <tools/color.hxx> 28 #include <comphelper/fileformat.h> 29 #include <comphelper/processfactory.hxx> 30 #include <o3tl/safeint.hxx> 31 #include <rtl/strbuf.hxx> 32 #include <sfx2/docfile.hxx> 33 #include <sfx2/docfilt.hxx> 34 #include <svl/itemset.hxx> 35 36 #include <com/sun/star/beans/XPropertySet.hpp> 37 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp> 38 #include <com/sun/star/packages/zip/ZipFileAccess.hpp> 39 #include <drawinglayer/XShapeDumper.hxx> 40 #include <com/sun/star/text/XTextField.hpp> 41 42 using namespace ::com::sun::star; 43 44 struct FileFormat 45 { 46 const char* pName; 47 const char* pFilterName; 48 const char* pTypeName; 49 const char* pUserData; 50 SfxFilterFlags nFormatType; 51 }; 52 53 // These values are taken from "Flags" in filter/source/config/fragments/filters/* 54 // You need to turn value of oor:name="Flags" to SfxFilterFlags::*, see 55 // include/comphelper/documentconstants.hxx for the possible values. 56 // Note: 3RDPARTYFILTER == SfxFilterFlags::STARONEFILTER 57 #define ODP_FORMAT_TYPE ( SfxFilterFlags::IMPORT | SfxFilterFlags::EXPORT | SfxFilterFlags::TEMPLATE | SfxFilterFlags::OWN | SfxFilterFlags::DEFAULT | SfxFilterFlags::ENCRYPTION | SfxFilterFlags::PREFERED ) 58 #define PPT_FORMAT_TYPE ( SfxFilterFlags::IMPORT | SfxFilterFlags::EXPORT | SfxFilterFlags::ALIEN ) 59 #define PPTX_FORMAT_TYPE ( SfxFilterFlags::IMPORT | SfxFilterFlags::EXPORT | SfxFilterFlags::ALIEN | SfxFilterFlags::STARONEFILTER | SfxFilterFlags::PREFERED ) 60 #define HTML_FORMAT_TYPE ( SfxFilterFlags::EXPORT | SfxFilterFlags::ALIEN ) 61 #define PDF_FORMAT_TYPE ( SfxFilterFlags::STARONEFILTER | SfxFilterFlags::ALIEN | SfxFilterFlags::IMPORT | SfxFilterFlags::PREFERED ) 62 #define FODG_FORMAT_TYPE (SfxFilterFlags::STARONEFILTER | SfxFilterFlags::OWN | SfxFilterFlags::IMPORT | SfxFilterFlags::EXPORT) 63 #define FODP_FORMAT_TYPE (SfxFilterFlags::STARONEFILTER | SfxFilterFlags::OWN | SfxFilterFlags::IMPORT | SfxFilterFlags::EXPORT) 64 #define SXI_FORMAT_TYPE (SfxFilterFlags::IMPORT | SfxFilterFlags::TEMPLATE | SfxFilterFlags::OWN | SfxFilterFlags::ALIEN | SfxFilterFlags::PREFERED | SfxFilterFlags::ENCRYPTION) 65 #define ODG_FORMAT_TYPE ( SfxFilterFlags::IMPORT | SfxFilterFlags::EXPORT | SfxFilterFlags::TEMPLATE | SfxFilterFlags::OWN | SfxFilterFlags::DEFAULT | SfxFilterFlags::ENCRYPTION | SfxFilterFlags::PREFERED ) 66 #define PPTM_FORMAT_TYPE ( SfxFilterFlags::IMPORT | SfxFilterFlags::EXPORT | SfxFilterFlags::ALIEN | SfxFilterFlags::STARONEFILTER | SfxFilterFlags::PREFERED ) 67 #define POTX_FORMAT_TYPE ( SfxFilterFlags::IMPORT | SfxFilterFlags::EXPORT | SfxFilterFlags::ALIEN | SfxFilterFlags::TEMPLATE | SfxFilterFlags::STARONEFILTER | SfxFilterFlags::PREFERED ) 68 69 /** List of file formats we support in Impress unit tests. 70 71 Taken from filter/source/config/fragments/filters/ too: 72 pName: The file extension. 73 pFilterName: <node oor:Name="..."> 74 pTypeName: <prop oor:Name="Type">...</prop> 75 nFormatType: <prop oor:name="Flags">...</prop> 76 */ 77 static FileFormat aFileFormats[] = 78 { 79 { "odp", "impress8", "impress8", "", ODP_FORMAT_TYPE }, 80 { "ppt", "MS PowerPoint 97", "impress_MS_PowerPoint_97", "sdfilt", PPT_FORMAT_TYPE }, 81 { "pptx", "Impress Office Open XML", "Office Open XML Presentation", "", PPTX_FORMAT_TYPE }, 82 { "html", "graphic_HTML", "graphic_HTML", "", HTML_FORMAT_TYPE }, 83 { "pdf", "draw_pdf_import", "pdf_Portable_Document_Format", "", PDF_FORMAT_TYPE }, 84 { "fodg", "OpenDocument Drawing Flat XML", "draw_ODG_FlatXML", "", FODG_FORMAT_TYPE }, 85 { "fodp", "OpenDocument Presentation Flat XML", "impress_ODP_FlatXML", "", FODP_FORMAT_TYPE }, 86 { "sxi", "StarOffice XML (Impress)", "impress_StarOffice_XML_Impress", "", SXI_FORMAT_TYPE }, 87 { "odg", "draw8", "draw8", "", ODG_FORMAT_TYPE }, 88 { "pptm", "Impress MS PowerPoint 2007 XML VBA", "MS PowerPoint 2007 XML VBA", "", PPTM_FORMAT_TYPE }, 89 { "potx", "Impress Office Open XML Template", "Office Open XML Presentation Template", "", POTX_FORMAT_TYPE }, 90 { nullptr, nullptr, nullptr, nullptr, SfxFilterFlags::NONE } 91 }; 92 93 #define ODP 0 94 #define PPT 1 95 #define PPTX 2 96 #define HTML 3 97 #define PDF 4 98 #define FODG 5 99 #define FODP 6 100 #define SXI 7 101 #define ODG 8 102 #define PPTM 9 103 #define POTX 10 104 105 /// Base class for filter tests loading or roundtripping a document, and asserting the document model. 106 class SdModelTestBase : public test::BootstrapFixture, public unotest::MacrosTest 107 { 108 private: 109 uno::Reference<uno::XInterface> mxDrawComponent; 110 uno::Reference<uno::XInterface> mxImpressComponent; 111 112 public: SdModelTestBase()113 SdModelTestBase() 114 {} 115 setUp()116 virtual void setUp() override 117 { 118 test::BootstrapFixture::setUp(); 119 120 // This is a bit of a fudge, we do this to ensure that ScGlobals::ensure, 121 // which is a private symbol to us, gets called 122 mxImpressComponent = getMultiServiceFactory()->createInstance("com.sun.star.comp.Draw.PresentationDocument"); 123 CPPUNIT_ASSERT_MESSAGE("no impress component!", mxImpressComponent.is()); 124 mxDrawComponent = getMultiServiceFactory()->createInstance("com.sun.star.comp.Draw.DrawingDocument"); 125 CPPUNIT_ASSERT_MESSAGE("no draw component!", mxDrawComponent.is()); 126 } 127 tearDown()128 virtual void tearDown() override 129 { 130 uno::Reference<lang::XComponent>(mxImpressComponent, uno::UNO_QUERY_THROW)->dispose(); 131 uno::Reference<lang::XComponent>(mxDrawComponent, uno::UNO_QUERY_THROW)->dispose(); 132 test::BootstrapFixture::tearDown(); 133 } 134 135 protected: 136 /// Load the document. loadURL(const OUString & rURL,sal_Int32 nFormat,std::shared_ptr<SfxAllItemSet> pParams=nullptr)137 sd::DrawDocShellRef loadURL( const OUString &rURL, sal_Int32 nFormat, std::shared_ptr<SfxAllItemSet> pParams = nullptr ) 138 { 139 FileFormat *pFmt = getFormat(nFormat); 140 CPPUNIT_ASSERT_MESSAGE( "missing filter info", pFmt->pName != nullptr ); 141 if ( std::strcmp(pFmt->pName, "odg") == 0) 142 { // Draw 143 SotClipboardFormatId nOptions = SotClipboardFormatId::NONE; 144 if (pFmt->nFormatType != SfxFilterFlags::NONE) 145 nOptions = SotClipboardFormatId::STARDRAW_8; 146 auto pFilter = std::make_shared<SfxFilter>( 147 OUString::createFromAscii( pFmt->pFilterName ), 148 OUString(), pFmt->nFormatType, nOptions, 149 OUString::createFromAscii( pFmt->pTypeName ), 150 OUString(), 151 OUString::createFromAscii( pFmt->pUserData ), 152 "private:factory/sdraw*" ); 153 pFilter->SetVersion(SOFFICE_FILEFORMAT_CURRENT); 154 155 ::sd::DrawDocShellRef xDocShRef = new ::sd::GraphicDocShell(SfxObjectCreateMode::EMBEDDED); 156 SfxMedium* pSrcMed = new SfxMedium(rURL, StreamMode::STD_READ, pFilter, std::move(pParams)); 157 if ( !xDocShRef->DoLoad(pSrcMed) || !xDocShRef.is() ) 158 { 159 if (xDocShRef.is()) 160 xDocShRef->DoClose(); 161 CPPUNIT_ASSERT_MESSAGE( OString("failed to load Draw doc" + OUStringToOString( rURL, RTL_TEXTENCODING_UTF8 )).getStr(), false ); 162 } 163 CPPUNIT_ASSERT_MESSAGE( "not in destruction", !xDocShRef->IsInDestruction() ); 164 return xDocShRef; 165 } 166 else // Impress 167 { 168 SotClipboardFormatId nOptions = SotClipboardFormatId::NONE; 169 if (pFmt->nFormatType != SfxFilterFlags::NONE) 170 nOptions = SotClipboardFormatId::STARIMPRESS_8; 171 auto pFilter = std::make_shared<SfxFilter>( 172 OUString::createFromAscii( pFmt->pFilterName ), 173 OUString(), pFmt->nFormatType, nOptions, 174 OUString::createFromAscii( pFmt->pTypeName ), 175 OUString(), 176 OUString::createFromAscii( pFmt->pUserData ), 177 "private:factory/simpress*" ); 178 pFilter->SetVersion(SOFFICE_FILEFORMAT_CURRENT); 179 180 ::sd::DrawDocShellRef xDocShRef = new ::sd::DrawDocShell(SfxObjectCreateMode::EMBEDDED, false, DocumentType::Impress); 181 SfxMedium* pSrcMed = new SfxMedium(rURL, StreamMode::STD_READ, pFilter, std::move(pParams)); 182 if ( !xDocShRef->DoLoad(pSrcMed) || !xDocShRef.is() ) 183 { 184 if (xDocShRef.is()) 185 xDocShRef->DoClose(); 186 CPPUNIT_ASSERT_MESSAGE( OString("failed to load " + OUStringToOString( rURL, RTL_TEXTENCODING_UTF8 )).getStr(), false ); 187 } 188 CPPUNIT_ASSERT_MESSAGE( "not in destruction", !xDocShRef->IsInDestruction() ); 189 return xDocShRef; 190 } 191 } 192 getFormat(sal_Int32 nExportType)193 FileFormat* getFormat(sal_Int32 nExportType) 194 { 195 FileFormat* pFormat = &aFileFormats[0]; 196 if (o3tl::make_unsigned(nExportType) < SAL_N_ELEMENTS(aFileFormats)) 197 pFormat = &aFileFormats[nExportType]; 198 return pFormat; 199 } 200 exportTo(sd::DrawDocShell * pShell,FileFormat const * pFormat,utl::TempFile const & rTempFile)201 void exportTo(sd::DrawDocShell* pShell, FileFormat const * pFormat, utl::TempFile const & rTempFile) 202 { 203 SfxMedium aStoreMedium(rTempFile.GetURL(), StreamMode::STD_WRITE); 204 if ( std::strcmp(pFormat->pName, "odg") == 0) 205 { // Draw 206 SotClipboardFormatId nExportFormat = SotClipboardFormatId::NONE; 207 if (pFormat->nFormatType == ODG_FORMAT_TYPE) 208 nExportFormat = SotClipboardFormatId::STARDRAW_8; 209 auto pExportFilter = std::make_shared<SfxFilter>( 210 OUString::createFromAscii(pFormat->pFilterName), 211 OUString(), pFormat->nFormatType, nExportFormat, 212 OUString::createFromAscii(pFormat->pTypeName), 213 OUString(), 214 OUString::createFromAscii(pFormat->pUserData), 215 "private:factory/sdraw*" ); 216 217 pExportFilter->SetVersion(SOFFICE_FILEFORMAT_CURRENT); 218 aStoreMedium.SetFilter(pExportFilter); 219 } 220 else // Impress 221 { 222 SotClipboardFormatId nExportFormat = SotClipboardFormatId::NONE; 223 if (pFormat->nFormatType == ODP_FORMAT_TYPE) 224 nExportFormat = SotClipboardFormatId::STARIMPRESS_8; 225 auto pExportFilter = std::make_shared<SfxFilter>( 226 OUString::createFromAscii(pFormat->pFilterName), 227 OUString(), pFormat->nFormatType, nExportFormat, 228 OUString::createFromAscii(pFormat->pTypeName), 229 OUString(), 230 OUString::createFromAscii(pFormat->pUserData), 231 "private:factory/simpress*" ); 232 233 pExportFilter->SetVersion(SOFFICE_FILEFORMAT_CURRENT); 234 aStoreMedium.SetFilter(pExportFilter); 235 } 236 pShell->ConvertTo(aStoreMedium); 237 pShell->DoClose(); 238 239 } 240 save(sd::DrawDocShell * pShell,FileFormat const * pFormat,utl::TempFile const & rTempFile)241 void save(sd::DrawDocShell* pShell, FileFormat const * pFormat, utl::TempFile const & rTempFile) 242 { 243 SfxMedium aStoreMedium(rTempFile.GetURL(), StreamMode::STD_WRITE); 244 if ( std::strcmp(pFormat->pName, "odg") == 0 ) 245 { // Draw 246 SotClipboardFormatId nExportFormat = SotClipboardFormatId::NONE; 247 if (pFormat->nFormatType == ODG_FORMAT_TYPE) 248 nExportFormat = SotClipboardFormatId::STARDRAW_8; 249 auto pExportFilter = std::make_shared<SfxFilter>( 250 OUString::createFromAscii(pFormat->pFilterName), 251 OUString(), pFormat->nFormatType, nExportFormat, 252 OUString::createFromAscii(pFormat->pTypeName), 253 OUString(), 254 OUString::createFromAscii(pFormat->pUserData), 255 "private:factory/sdraw*" ); 256 pExportFilter->SetVersion(SOFFICE_FILEFORMAT_CURRENT); 257 aStoreMedium.SetFilter(pExportFilter); 258 } 259 else // Impress 260 { 261 SotClipboardFormatId nExportFormat = SotClipboardFormatId::NONE; 262 if (pFormat->nFormatType == ODP_FORMAT_TYPE) 263 nExportFormat = SotClipboardFormatId::STARCHART_8; 264 auto pExportFilter = std::make_shared<SfxFilter>( 265 OUString::createFromAscii(pFormat->pFilterName), 266 OUString(), pFormat->nFormatType, nExportFormat, 267 OUString::createFromAscii(pFormat->pTypeName), 268 OUString(), 269 OUString::createFromAscii(pFormat->pUserData), 270 "private:factory/simpress*" ); 271 pExportFilter->SetVersion(SOFFICE_FILEFORMAT_CURRENT); 272 aStoreMedium.SetFilter(pExportFilter); 273 } 274 pShell->DoSaveAs(aStoreMedium); 275 pShell->DoClose(); 276 } 277 saveAndReload(sd::DrawDocShell * pShell,sal_Int32 nExportType,utl::TempFile * pTempFile=nullptr)278 sd::DrawDocShellRef saveAndReload(sd::DrawDocShell *pShell, sal_Int32 nExportType, 279 utl::TempFile * pTempFile = nullptr) 280 { 281 FileFormat* pFormat = getFormat(nExportType); 282 std::unique_ptr<utl::TempFile> pNewTempFile; 283 if (!pTempFile) 284 { 285 pNewTempFile.reset(new utl::TempFile); 286 pTempFile = pNewTempFile.get(); 287 } 288 save(pShell, pFormat, *pTempFile); 289 if (nExportType == ODP || nExportType == ODG) 290 { 291 BootstrapFixture::validate(pTempFile->GetFileName(), test::ODF); 292 } 293 else if(nExportType == PPTX) 294 { 295 BootstrapFixture::validate(pTempFile->GetFileName(), test::OOXML); 296 } 297 else if(nExportType == PPT) 298 { 299 BootstrapFixture::validate(pTempFile->GetFileName(), test::MSBINARY); 300 } 301 pTempFile->EnableKillingFile(); 302 return loadURL(pTempFile->GetURL(), nExportType); 303 } 304 305 /** Dump shapes in xDocShRef, and compare the dump against content of pShapesDumpFileNameBase<number>.xml. 306 307 @param bCreate Instead of comparing to the reference file(s), create it/them. 308 */ compareWithShapesDump(::sd::DrawDocShellRef xDocShRef,std::u16string_view rShapesDumpFileNameBase,bool bCreate)309 void compareWithShapesDump( ::sd::DrawDocShellRef xDocShRef, std::u16string_view rShapesDumpFileNameBase, bool bCreate ) 310 { 311 CPPUNIT_ASSERT_MESSAGE( "failed to load", xDocShRef.is() ); 312 CPPUNIT_ASSERT_MESSAGE( "not in destruction", !xDocShRef->IsInDestruction() ); 313 314 uno::Reference<frame::XModel> xTempModel(xDocShRef->GetDoc()->getUnoModel(), uno::UNO_QUERY_THROW); 315 uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier (xTempModel, uno::UNO_QUERY_THROW); 316 uno::Reference< drawing::XDrawPages > xDrawPages = xDrawPagesSupplier->getDrawPages(); 317 CPPUNIT_ASSERT(xDrawPages.is()); 318 319 sal_Int32 nLength = xDrawPages->getCount(); 320 for (sal_Int32 i = 0; i < nLength; ++i) 321 { 322 uno::Reference<drawing::XDrawPage> xDrawPage; 323 uno::Any aAny = xDrawPages->getByIndex(i); 324 aAny >>= xDrawPage; 325 uno::Reference< drawing::XShapes > xShapes(xDrawPage, uno::UNO_QUERY_THROW); 326 OUString aString = XShapeDumper::dump(xShapes); 327 328 OString aFileName = OUStringToOString( rShapesDumpFileNameBase, RTL_TEXTENCODING_UTF8 ) + 329 OString::number(i) + ".xml"; 330 331 if ( bCreate ) 332 { 333 std::ofstream aStream( aFileName.getStr(), std::ofstream::out | std::ofstream::binary ); 334 aStream << aString; 335 aStream.close(); 336 } 337 else 338 { 339 doXMLDiff(aFileName.getStr(), 340 OUStringToOString(aString, RTL_TEXTENCODING_UTF8).getStr(), 341 static_cast<int>(aString.getLength()), 342 OUStringToOString( 343 m_directories.getPathFromSrc(u"/sd/qa/unit/data/tolerance.xml"), 344 RTL_TEXTENCODING_UTF8).getStr()); 345 } 346 } 347 xDocShRef->DoClose(); 348 } 349 getDoc(sd::DrawDocShellRef xDocShRef)350 uno::Reference< drawing::XDrawPagesSupplier > getDoc( sd::DrawDocShellRef xDocShRef ) 351 { 352 uno::Reference< drawing::XDrawPagesSupplier > xDoc ( 353 xDocShRef->GetDoc()->getUnoModel(), uno::UNO_QUERY_THROW ); 354 return xDoc; 355 } 356 getPage(int nPage,sd::DrawDocShellRef xDocShRef)357 uno::Reference< drawing::XDrawPage > getPage( int nPage, sd::DrawDocShellRef xDocShRef ) 358 { 359 uno::Reference< drawing::XDrawPagesSupplier > xDoc( getDoc( xDocShRef ) ); 360 uno::Reference< drawing::XDrawPage > xPage( xDoc->getDrawPages()->getByIndex( nPage ), uno::UNO_QUERY_THROW ); 361 return xPage; 362 } 363 364 // very confusing ... UNO index-based access to pages is 0-based. This one is 1-based GetPage(int nPage,sd::DrawDocShellRef xDocShRef)365 const SdrPage* GetPage( int nPage, sd::DrawDocShellRef xDocShRef ) 366 { 367 SdDrawDocument* pDoc = xDocShRef->GetDoc() ; 368 CPPUNIT_ASSERT_MESSAGE( "no document", pDoc != nullptr ); 369 370 const SdrPage* pPage = pDoc->GetPage( nPage ); 371 CPPUNIT_ASSERT_MESSAGE( "no page", pPage != nullptr ); 372 return pPage; 373 } 374 getShape(int nShape,uno::Reference<drawing::XDrawPage> const & xPage)375 uno::Reference< beans::XPropertySet > getShape( int nShape, uno::Reference< drawing::XDrawPage > const & xPage ) 376 { 377 uno::Reference< beans::XPropertySet > xShape( xPage->getByIndex( nShape ), uno::UNO_QUERY ); 378 CPPUNIT_ASSERT_MESSAGE( "Failed to load shape", xShape.is() ); 379 return xShape; 380 } 381 382 // Nth shape on Mth page getShapeFromPage(int nShape,int nPage,sd::DrawDocShellRef xDocShRef)383 uno::Reference< beans::XPropertySet > getShapeFromPage( int nShape, int nPage, sd::DrawDocShellRef xDocShRef ) 384 { 385 uno::Reference< drawing::XDrawPage > xPage ( getPage( nPage, xDocShRef ) ); 386 uno::Reference< beans::XPropertySet > xShape( getShape( nShape, xPage ) ); 387 CPPUNIT_ASSERT_MESSAGE( "Failed to load shape", xShape.is() ); 388 389 return xShape; 390 } 391 392 // Nth paragraph of text in given text shape getParagraphFromShape(int nPara,uno::Reference<beans::XPropertySet> const & xShape)393 uno::Reference< text::XTextRange > getParagraphFromShape( int nPara, uno::Reference< beans::XPropertySet > const & xShape ) 394 { 395 uno::Reference< text::XText > xText = uno::Reference< text::XTextRange>( xShape, uno::UNO_QUERY_THROW )->getText(); 396 CPPUNIT_ASSERT_MESSAGE( "Not a text shape", xText.is() ); 397 398 uno::Reference< container::XEnumerationAccess > paraEnumAccess( xText, uno::UNO_QUERY ); 399 uno::Reference< container::XEnumeration > paraEnum( paraEnumAccess->createEnumeration() ); 400 401 for ( int i = 0; i < nPara; ++i ) 402 paraEnum->nextElement(); 403 404 uno::Reference< text::XTextRange > xParagraph( paraEnum->nextElement(), uno::UNO_QUERY_THROW ); 405 406 return xParagraph; 407 } 408 getRunFromParagraph(int nRun,uno::Reference<text::XTextRange> const & xParagraph)409 uno::Reference< text::XTextRange > getRunFromParagraph( int nRun, uno::Reference< text::XTextRange > const & xParagraph ) 410 { 411 uno::Reference< container::XEnumerationAccess > runEnumAccess(xParagraph, uno::UNO_QUERY); 412 uno::Reference< container::XEnumeration > runEnum = runEnumAccess->createEnumeration(); 413 414 for ( int i = 0; i < nRun; ++i ) 415 runEnum->nextElement(); 416 417 uno::Reference< text::XTextRange > xRun( runEnum->nextElement(), uno::UNO_QUERY); 418 419 return xRun; 420 } 421 getTextFieldFromPage(int nRun,int nPara,int nShape,int nPage,sd::DrawDocShellRef xDocShRef)422 uno::Reference<text::XTextField> getTextFieldFromPage(int nRun, int nPara, int nShape, int nPage, sd::DrawDocShellRef xDocShRef) 423 { 424 // get TextShape 1 from the first page 425 uno::Reference< beans::XPropertySet > xShape( getShapeFromPage( nShape, nPage, xDocShRef ) ); 426 427 // Get first paragraph 428 uno::Reference<text::XTextRange> xParagraph( getParagraphFromShape( nPara, xShape ) ); 429 430 // first chunk of text 431 uno::Reference<text::XTextRange> xRun( getRunFromParagraph( nRun, xParagraph ) ); 432 433 uno::Reference< beans::XPropertySet > xPropSet( xRun, uno::UNO_QUERY_THROW ); 434 435 uno::Reference<text::XTextField> xField; 436 xPropSet->getPropertyValue("TextField") >>= xField; 437 return xField; 438 } 439 440 }; 441 442 class SdModelTestBaseXML 443 : public SdModelTestBase, public XmlTestTools 444 { 445 446 public: parseExportStream(utl::TempFile const & rTempFile,const OUString & rStreamName)447 std::unique_ptr<SvStream> parseExportStream(utl::TempFile const & rTempFile, const OUString& rStreamName) 448 { 449 // Read the stream we're interested in. 450 OUString const url(rTempFile.GetURL()); 451 uno::Reference<packages::zip::XZipFileAccess2> const xZipNames(packages::zip::ZipFileAccess::createWithURL( 452 comphelper::getComponentContext(m_xSFactory), url)); 453 uno::Reference<io::XInputStream> const xInputStream(xZipNames->getByName(rStreamName), uno::UNO_QUERY); 454 std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true)); 455 return pStream; 456 } 457 parseExport(utl::TempFile const & rTempFile,OUString const & rStreamName)458 xmlDocUniquePtr parseExport(utl::TempFile const & rTempFile, OUString const& rStreamName) 459 { 460 std::unique_ptr<SvStream> const pStream(parseExportStream(rTempFile, rStreamName)); 461 xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get()); 462 OUString const url(rTempFile.GetURL()); 463 pXmlDoc->name = reinterpret_cast<char *>(xmlStrdup( 464 reinterpret_cast<xmlChar const *>(OUStringToOString(url, RTL_TEXTENCODING_UTF8).getStr()))); 465 return pXmlDoc; 466 } 467 468 }; 469 470 CPPUNIT_NS_BEGIN 471 472 template<> struct assertion_traits<Color> 473 { equalassertion_traits474 static bool equal( const Color& c1, const Color& c2 ) 475 { 476 return c1 == c2; 477 } 478 toStringassertion_traits479 static std::string toString( const Color& c ) 480 { 481 OStringStream ost; 482 ost << "Color: R:" << static_cast<int>(c.GetRed()) 483 << " G:" << static_cast<int>(c.GetGreen()) 484 << " B:" << static_cast<int>(c.GetBlue()) 485 << " A:" << static_cast<int>(255 - c.GetAlpha()); 486 return ost.str(); 487 } 488 }; 489 490 template<> struct assertion_traits<tools::Rectangle> 491 { equalassertion_traits492 static bool equal( const tools::Rectangle& r1, const tools::Rectangle& r2 ) 493 { 494 return r1 == r2; 495 } 496 toStringassertion_traits497 static std::string toString( const tools::Rectangle& r) 498 { 499 OStringStream ost; 500 ost << "Rect P: [" << r.Top() << ", " << r.Left() << "] " 501 "S: [" << r.GetWidth() << ", " << r.GetHeight() << "]"; 502 return ost.str(); 503 } 504 }; 505 506 CPPUNIT_NS_END 507 508 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 509