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