LibreOffice Module svx (master)  1
galobj.cxx
Go to the documentation of this file.
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  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <sal/config.h>
21 
22 #include <com/sun/star/frame/XModel.hpp>
23 #include <com/sun/star/lang/XUnoTunnel.hpp>
24 #include <sfx2/objsh.hxx>
25 #include <comphelper/fileformat.h>
27 #include <tools/vcompat.hxx>
28 #include <tools/helpers.hxx>
29 #include <vcl/virdev.hxx>
30 #include <svx/fmmodel.hxx>
31 #include <svx/fmview.hxx>
32 #include <svx/fmpage.hxx>
33 #include <svx/galmisc.hxx>
34 #include <galobj.hxx>
35 #include <vcl/dibtools.hxx>
36 #include <vcl/filter/SvmReader.hxx>
37 #include <vcl/filter/SvmWriter.hxx>
38 #include "gallerydrawmodel.hxx"
39 #include <bitmaps.hlst>
40 
41 using namespace ::com::sun::star;
42 
43 SgaObject::SgaObject()
44 : bIsValid ( false ),
45  bIsThumbBmp ( true )
46 {
47 }
48 
49 SgaObject::SgaObject(const SgaObject& aObject)
50  : aThumbBmp(aObject.aThumbBmp)
51  , aThumbMtf(aObject.aThumbMtf)
52  , aURL(aObject.aURL)
53  , aTitle(aObject.aTitle)
54  , bIsValid(aObject.bIsValid)
55  , bIsThumbBmp(aObject.bIsThumbBmp)
56 {
57 }
58 
59 BitmapEx SgaObject::createPreviewBitmapEx(const Size& rSizePixel) const
60 {
61  BitmapEx aRetval;
62 
63  if(rSizePixel.Width() && rSizePixel.Height())
64  {
65  if(SgaObjKind::Sound == GetObjKind())
66  {
67  aRetval = BitmapEx(RID_SVXBMP_GALLERY_MEDIA);
68  }
69  else if(IsThumbBitmap())
70  {
71  aRetval = GetThumbBmp();
72  }
73  else
74  {
75  const Graphic aGraphic(GetThumbMtf());
76 
77  aRetval = aGraphic.GetBitmapEx();
78  }
79 
80  if(!aRetval.IsEmpty())
81  {
82  const Size aCurrentSizePixel(aRetval.GetSizePixel());
83  const double fScaleX(static_cast<double>(rSizePixel.Width()) / static_cast<double>(aCurrentSizePixel.Width()));
84  const double fScaleY(static_cast<double>(rSizePixel.Height()) / static_cast<double>(aCurrentSizePixel.Height()));
85  const double fScale(std::min(fScaleX, fScaleY));
86 
87  // only scale when need to decrease, no need to make bigger as original. Also
88  // prevent scaling close to 1.0 which is not needed for pixel graphics
89  if(fScale < 1.0 && fabs(1.0 - fScale) > 0.005)
90  {
91  aRetval.Scale(fScale, fScale, BmpScaleFlag::BestQuality);
92  }
93  }
94  }
95 
96  return aRetval;
97 }
98 
99 bool SgaObject::CreateThumb( const Graphic& rGraphic )
100 {
101  bool bRet = false;
102 
103  if( rGraphic.GetType() == GraphicType::Bitmap )
104  {
105  BitmapEx aBmpEx( rGraphic.GetBitmapEx() );
106  Size aBmpSize( aBmpEx.GetSizePixel() );
107 
108  if( aBmpSize.Width() && aBmpSize.Height() )
109  {
110  if( aBmpEx.GetPrefMapMode().GetMapUnit() != MapUnit::MapPixel &&
111  aBmpEx.GetPrefSize().Width() > 0 &&
112  aBmpEx.GetPrefSize().Height() > 0 )
113  {
114  Size aLogSize( OutputDevice::LogicToLogic(aBmpEx.GetPrefSize(), aBmpEx.GetPrefMapMode(), MapMode(MapUnit::Map100thMM)) );
115 
116  if( !aLogSize.IsEmpty() )
117  {
118  double fFactorLog = static_cast< double >( aLogSize.Width() ) / aLogSize.Height();
119  double fFactorPix = static_cast< double >( aBmpSize.Width() ) / aBmpSize.Height();
120 
121  if( fFactorPix > fFactorLog )
122  aBmpSize.setWidth( FRound( aBmpSize.Height() * fFactorLog ) );
123  else
124  aBmpSize.setHeight( FRound( aBmpSize.Width() / fFactorLog ) );
125 
126  aBmpEx.Scale(aBmpSize, BmpScaleFlag::BestQuality);
127  }
128  }
129 
130  // take over BitmapEx
131  aThumbBmp = aBmpEx;
132 
133  if( ( aBmpSize.Width() <= S_THUMB ) && ( aBmpSize.Height() <= S_THUMB ) )
134  {
135  aThumbBmp.Convert( BmpConversion::N8BitColors );
136  bRet = true;
137  }
138  else
139  {
140  const float fFactor = static_cast<float>(aBmpSize.Width()) / aBmpSize.Height();
141  const Size aNewSize( std::max( tools::Long(fFactor < 1. ? S_THUMB * fFactor : S_THUMB), tools::Long(8) ),
142  std::max( tools::Long(fFactor < 1. ? S_THUMB : S_THUMB / fFactor), tools::Long(8) ) );
143  if(aThumbBmp.Scale(
144  static_cast<double>(aNewSize.Width()) / aBmpSize.Width(),
145  static_cast<double>(aNewSize.Height()) / aBmpSize.Height(),
146  BmpScaleFlag::BestQuality ) )
147  {
148  aThumbBmp.Convert( BmpConversion::N8BitColors );
149  bRet = true;
150  }
151  }
152  }
153  }
154  else if( rGraphic.GetType() == GraphicType::GdiMetafile )
155  {
156  const Size aPrefSize( rGraphic.GetPrefSize() );
157  const double fFactor = static_cast<double>(aPrefSize.Width()) / static_cast<double>(aPrefSize.Height());
158  Size aSize( S_THUMB, S_THUMB );
159  if ( fFactor < 1.0 )
160  aSize.setWidth( static_cast<sal_Int32>( S_THUMB * fFactor ) );
161  else
162  aSize.setHeight( static_cast<sal_Int32>( S_THUMB / fFactor ) );
163 
164  const GraphicConversionParameters aParameters(aSize, false, true, true /*TODO: extra ", true" post-#i121194#*/);
165  aThumbBmp = rGraphic.GetBitmapEx(aParameters);
166 
167  if( !aThumbBmp.IsEmpty() )
168  {
169  aThumbBmp.Convert( BmpConversion::N8BitColors );
170  bRet = true;
171  }
172  }
173 
174  return bRet;
175 }
176 
177 void SgaObject::WriteData( SvStream& rOut, const OUString& rDestDir ) const
178 {
179  static const sal_uInt32 nInventor = COMPAT_FORMAT( 'S', 'G', 'A', '3' );
180 
181  rOut.WriteUInt32( nInventor ).WriteUInt16( 0x0004 ).WriteUInt16( GetVersion() ).WriteUInt16( static_cast<sal_uInt16>(GetObjKind()) );
182  rOut.WriteBool( bIsThumbBmp );
183 
184  if( bIsThumbBmp )
185  {
186  const SvStreamCompressFlags nOldCompressMode = rOut.GetCompressMode();
187  const sal_Int32 nOldVersion = rOut.GetVersion();
188 
189  rOut.SetCompressMode( SvStreamCompressFlags::ZBITMAP );
190  rOut.SetVersion( SOFFICE_FILEFORMAT_50 );
191 
192  WriteDIBBitmapEx(aThumbBmp, rOut);
193 
194  rOut.SetVersion( nOldVersion );
195  rOut.SetCompressMode( nOldCompressMode );
196  }
197  else
198  {
199  if(!rOut.GetError())
200  {
201  SvmWriter aWriter(rOut);
202  aWriter.Write(aThumbMtf);
203  }
204  }
205 
206  OUString aURLWithoutDestDir = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
207  aURLWithoutDestDir = aURLWithoutDestDir.replaceFirst(rDestDir, "");
208  write_uInt16_lenPrefixed_uInt8s_FromOUString(rOut, aURLWithoutDestDir, RTL_TEXTENCODING_UTF8);
209 }
210 
211 void SgaObject::ReadData(SvStream& rIn, sal_uInt16& rReadVersion )
212 {
213  sal_uInt32 nTmp32;
214  sal_uInt16 nTmp16;
215 
216  rIn.ReadUInt32( nTmp32 ).ReadUInt16( nTmp16 ).ReadUInt16( rReadVersion ).ReadUInt16( nTmp16 ).ReadCharAsBool( bIsThumbBmp );
217 
218  if( bIsThumbBmp )
219  {
220  ReadDIBBitmapEx(aThumbBmp, rIn);
221  }
222  else
223  {
224  SvmReader aReader( rIn );
225  aReader.Read( aThumbMtf );
226  }
227 
228  OUString aTmpStr = read_uInt16_lenPrefixed_uInt8s_ToOUString(rIn, RTL_TEXTENCODING_UTF8);
229  aURL = INetURLObject(aTmpStr);
230 }
231 
232 OUString const & SgaObject::GetTitle() const
233 {
234  return aTitle;
235 }
236 
237 void SgaObject::SetTitle( const OUString& rTitle )
238 {
239  aTitle = rTitle;
240 }
241 
242 SvStream& WriteSgaObject( SvStream& rOut, const SgaObject& rObj )
243 {
244  rObj.WriteData( rOut, "" );
245  return rOut;
246 }
247 
248 SvStream& ReadSgaObject( SvStream& rIn, SgaObject& rObj )
249 {
250  sal_uInt16 nReadVersion;
251 
252  rObj.ReadData( rIn, nReadVersion );
253  rObj.bIsValid = ( rIn.GetError() == ERRCODE_NONE );
254 
255  return rIn;
256 }
257 
259 {
260 }
261 
263 {
264  Graphic aGraphic;
265  OUString aFilter;
266 
267  if ( GalleryGraphicImportRet::IMPORT_NONE != GalleryGraphicImport( rURL, aGraphic, aFilter ) )
268  Init( aGraphic, rURL );
269 }
270 
271 SgaObjectBmp::SgaObjectBmp( const Graphic& rGraphic, const INetURLObject& rURL )
272 {
273  if( FileExists( rURL ) )
274  Init( rGraphic, rURL );
275 }
276 
277 void SgaObjectBmp::Init( const Graphic& rGraphic, const INetURLObject& rURL )
278 {
279  aURL = rURL;
280  bIsValid = CreateThumb( rGraphic );
281 }
282 
283 void SgaObjectBmp::WriteData( SvStream& rOut, const OUString& rDestDir ) const
284 {
285  // Set version
286  SgaObject::WriteData( rOut, rDestDir );
287  char const aDummy[ 10 ] = { 0 };
288  rOut.WriteBytes(aDummy, 10);
290  write_uInt16_lenPrefixed_uInt8s_FromOUString(rOut, aTitle, RTL_TEXTENCODING_UTF8);
291 }
292 
293 void SgaObjectBmp::ReadData( SvStream& rIn, sal_uInt16& rReadVersion )
294 {
295 
296  SgaObject::ReadData( rIn, rReadVersion );
297  rIn.SeekRel( 10 ); // 16, 16, 32, 16
299 
300  if( rReadVersion >= 5 )
301  aTitle = read_uInt16_lenPrefixed_uInt8s_ToOUString(rIn, RTL_TEXTENCODING_UTF8);
302 }
303 
304 
306  eSoundType( SOUND_STANDARD )
307 {
308 }
309 
311  eSoundType( SOUND_STANDARD )
312 {
313 
314  if( FileExists( rURL ) )
315  {
316  aURL = rURL;
317  aThumbBmp = Bitmap(Size(1, 1), vcl::PixelFormat::N1_BPP);
318  bIsValid = true;
319  }
320  else
321  bIsValid = false;
322 }
323 
325 {
326 }
327 
329 {
330  OUString sId;
331 
332  switch( eSoundType )
333  {
334  case SOUND_COMPUTER: sId = RID_SVXBMP_GALLERY_SOUND_1; break;
335  case SOUND_MISC: sId = RID_SVXBMP_GALLERY_SOUND_2; break;
336  case SOUND_MUSIC: sId = RID_SVXBMP_GALLERY_SOUND_3; break;
337  case SOUND_NATURE: sId = RID_SVXBMP_GALLERY_SOUND_4; break;
338  case SOUND_SPEECH: sId = RID_SVXBMP_GALLERY_SOUND_5; break;
339  case SOUND_TECHNIC: sId = RID_SVXBMP_GALLERY_SOUND_6; break;
340  case SOUND_ANIMAL: sId = RID_SVXBMP_GALLERY_SOUND_7; break;
341 
342  // standard
343  default:
344  sId = RID_SVXBMP_GALLERY_MEDIA;
345  break;
346  }
347 
348  const BitmapEx aBmpEx(sId);
349 
350  return aBmpEx;
351 }
352 
353 void SgaObjectSound::WriteData( SvStream& rOut, const OUString& rDestDir ) const
354 {
355  SgaObject::WriteData( rOut, rDestDir );
356  rOut.WriteUInt16( eSoundType );
357  write_uInt16_lenPrefixed_uInt8s_FromOUString(rOut, aTitle, RTL_TEXTENCODING_UTF8);
358 }
359 
360 void SgaObjectSound::ReadData( SvStream& rIn, sal_uInt16& rReadVersion )
361 {
362  SgaObject::ReadData( rIn, rReadVersion );
363 
364  if( rReadVersion >= 5 )
365  {
366  sal_uInt16 nTmp16;
367 
368  rIn.ReadUInt16( nTmp16 ); eSoundType = static_cast<GalSoundType>(nTmp16);
369 
370  if( rReadVersion >= 6 )
371  aTitle = read_uInt16_lenPrefixed_uInt8s_ToOUString(rIn, RTL_TEXTENCODING_UTF8);
372  }
373 }
374 
376 {
377 }
378 
380  const INetURLObject& rURL )
381 {
382  aURL = rURL;
383  bIsValid = CreateThumb( rGraphic );
384 }
385 
387 {
388 }
389 
390 SgaObjectINet::SgaObjectINet( const Graphic& rGraphic, const INetURLObject& rURL ) :
391  SgaObjectAnim ( rGraphic, rURL )
392 {
393 }
394 
396 {
397 }
398 
400 {
401  aURL = rURL;
402  bIsValid = CreateThumb( rModel );
403 }
404 
405 
407 : mpFormModel( nullptr )
408 {
410 
411  if( !mxDoc.Is() )
412  return;
413 
414  mxDoc->DoInitNew();
415 
417  = dynamic_cast<FmFormModel*>(comphelper::getFromUnoTunnel<SdrModel>(mxDoc->GetModel()));
418  if (mpFormModel)
419  {
421  }
422 }
423 
425 {
426  if( mxDoc.Is() )
427  mxDoc->DoClose();
428 
429 }
430 
432 {
433  SvxGalleryDrawModel aModel;
434 
435  if( aModel.GetModel() )
436  {
437  if( GallerySvDrawImport( rIStm, *aModel.GetModel() ) )
438  {
439  aURL = rURL;
440  bIsValid = CreateThumb( *aModel.GetModel() );
441  }
442  }
443 }
444 
446 {
447  Graphic aGraphic;
448  ImageMap aImageMap;
449  bool bRet = false;
450 
451  if ( CreateIMapGraphic( rModel, aGraphic, aImageMap ) )
452  {
453  bRet = SgaObject::CreateThumb( aGraphic );
454  }
455  else
456  {
457  const FmFormPage* pPage = static_cast< const FmFormPage* >(rModel.GetPage(0));
458 
459  if(pPage)
460  {
461  const tools::Rectangle aObjRect(pPage->GetAllObjBoundRect());
462 
463  if(aObjRect.GetWidth() && aObjRect.GetHeight())
464  {
466  FmFormView aView(const_cast< FmFormModel& >(rModel), pVDev);
467 
468  aView.ShowSdrPage(const_cast< FmFormPage* >(pPage));
469  aView.MarkAllObj();
470  aThumbBmp = aView.GetMarkedObjBitmapEx(true);
471  aGraphic = Graphic(aThumbBmp);
472  bRet = SgaObject::CreateThumb(aGraphic);
473  }
474  }
475  }
476 
477  return bRet;
478 }
479 
480 void SgaObjectSvDraw::WriteData( SvStream& rOut, const OUString& rDestDir ) const
481 {
482  SgaObject::WriteData( rOut, rDestDir );
483  write_uInt16_lenPrefixed_uInt8s_FromOUString(rOut, aTitle, RTL_TEXTENCODING_UTF8);
484 }
485 
486 void SgaObjectSvDraw::ReadData( SvStream& rIn, sal_uInt16& rReadVersion )
487 {
488  SgaObject::ReadData( rIn, rReadVersion );
489 
490  if( rReadVersion >= 5 )
491  aTitle = read_uInt16_lenPrefixed_uInt8s_ToOUString(rIn, RTL_TEXTENCODING_UTF8);
492 }
493 
494 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SvStream & WriteBool(bool b)
virtual void ReadData(SvStream &rIn, sal_uInt16 &rReadVersion) override
Definition: galobj.cxx:360
virtual ~SgaObjectSound() override
Definition: galobj.cxx:324
URL aURL
virtual BitmapEx GetThumbBmp() const override
Definition: galobj.cxx:328
SvStream & WriteUInt16(sal_uInt16 nUInt16)
bool CreateIMapGraphic(const FmFormModel &rModel, Graphic &rGraphic, ImageMap &rImageMap)
Definition: galmisc.cxx:120
SvStream & ReadUInt16(sal_uInt16 &rUInt16)
SAL_WARN_UNUSED_RESULT Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
SvStream & ReadSgaObject(SvStream &rIn, SgaObject &rObj)
Definition: galobj.cxx:248
const tools::Rectangle & GetAllObjBoundRect() const
Definition: svdpage.cxx:742
virtual void WriteData(SvStream &rOut, const OUString &rDestDir) const override
Definition: galobj.cxx:353
bool CreateThumb(const FmFormModel &rModel)
Definition: galobj.cxx:445
sal_Int32 GetVersion() const
bool Is() const
virtual void WriteData(SvStream &rOut, const OUString &rDestDir) const override
Definition: galobj.cxx:480
bool Scale(const Size &rNewSize, BmpScaleFlag nScaleFlag=BmpScaleFlag::Default)
long Long
SvStream & ReadCharAsBool(bool &rBool)
css::uno::Reference< css::frame::XModel3 > GetModel() const
virtual SdrPageView * ShowSdrPage(SdrPage *pPage) override
Definition: fmview.cxx:297
SvStream & WriteSgaObject(SvStream &rOut, const SgaObject &rObj)
Definition: galobj.cxx:242
FmFormModel * GetModel() const
FmFormModel * mpFormModel
SvStreamCompressFlags GetCompressMode() const
bool Convert(BmpConversion eConversion)
sal_uInt64 SeekRel(sal_Int64 nPos)
constexpr tools::Long Width() const
OString read_uInt16_lenPrefixed_uInt8s_ToOString(SvStream &rStrm)
ErrCode GetError() const
bool ReadDIBBitmapEx(BitmapEx &rTarget, SvStream &rIStm, bool bFileHeader, bool bMSOFormat)
std::size_t write_uInt16_lenPrefixed_uInt8s_FromOUString(SvStream &rStrm, std::u16string_view rStr, rtl_TextEncoding eEnc)
SvStream & WriteUInt32(sal_uInt32 nUInt32)
#define S_THUMB
Definition: galobj.hxx:29
static bool FileExists(const INetURLObject &rURL, std::u16string_view rExt)
virtual void ReadData(SvStream &rIn, sal_uInt16 &rReadVersion) override
Definition: galobj.cxx:486
SvStream & ReadUInt32(sal_uInt32 &rUInt32)
void MarkAllObj(SdrPageView *pPV=nullptr)
Definition: svdmrkv.cxx:2538
bool IsEmpty() const
virtual void InsertPage(SdrPage *pPage, sal_uInt16 nPos=0xFFFF) override
Definition: fmmodel.cxx:80
bool WriteDIBBitmapEx(const BitmapEx &rSource, SvStream &rOStm)
OUString read_uInt16_lenPrefixed_uInt8s_ToOUString(SvStream &rStrm, rtl_TextEncoding eEnc)
GalleryGraphicImportRet GalleryGraphicImport(const INetURLObject &rURL, Graphic &rGraphic, OUString &rFilterName)
Definition: galmisc.cxx:51
GraphicType GetType() const
tools::Long FRound(double fVal)
sal_uInt32 COMPAT_FORMAT(char char1, char char2, char char3, char char4)
static SfxObjectShell * CreateObjectByFactoryName(const OUString &rURL, SfxObjectCreateMode=SfxObjectCreateMode::STANDARD)
virtual void ReadData(SvStream &rIn, sal_uInt16 &rReadVersion) override
Definition: galobj.cxx:293
const SdrPage * GetPage(sal_uInt16 nPgNum) const
Definition: svdmodel.cxx:1801
std::size_t WriteBytes(const void *pData, std::size_t nSize)
SvStreamCompressFlags
BitmapEx GetBitmapEx(const GraphicConversionParameters &rParameters=GraphicConversionParameters()) const
void SetVersion(sal_Int32 n)
GalSoundType eSoundType
Definition: galobj.hxx:95
void Init(const Graphic &rGraphic, const INetURLObject &rURL)
Definition: galobj.cxx:277
bool GallerySvDrawImport(SvStream &rIStm, SdrModel &rModel)
Definition: galmisc.cxx:76
virtual rtl::Reference< SdrPage > AllocPage(bool bMasterPage) override
Definition: fmmodel.cxx:75
std::size_t write_uInt16_lenPrefixed_uInt8s_FromOString(SvStream &rStrm, std::string_view rStr)
GalSoundType
Definition: galobj.hxx:32
Size GetPrefSize() const
virtual void WriteData(SvStream &rOut, const OUString &rDestDir) const override
Definition: galobj.cxx:283
#define ERRCODE_NONE
constexpr tools::Long Height() const
bool DoInitNew(SfxMedium *pMedium=nullptr)
BitmapEx GetMarkedObjBitmapEx(bool bNoVDevIfOneBmpMarked=false, const sal_uInt32 nMaximumQuadraticPixels=500000, const std::optional< Size > &rTargetDPI=std::nullopt) const
Definition: svdxcgv.cxx:428
SfxObjectShellLock mxDoc
sal_uInt16 GetVersion(sal_uInt16)
Definition: legacyitem.cxx:29
void SetCompressMode(SvStreamCompressFlags nNewMode)
const Size & GetSizePixel() const
OUString sId