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