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