Line data Source code
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 <vcl/outdev.hxx>
21 : #include <vcl/svapp.hxx>
22 : #include <vcl/graph.hxx>
23 : #include <vcl/metaact.hxx>
24 : #include <impgraph.hxx>
25 : #include <comphelper/processfactory.hxx>
26 : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
27 : #include <com/sun/star/graphic/GraphicProvider.hpp>
28 : #include <com/sun/star/graphic/XGraphicProvider.hpp>
29 : #include <com/sun/star/lang/XUnoTunnel.hpp>
30 : #include <com/sun/star/lang/XTypeProvider.hpp>
31 : #include <com/sun/star/graphic/XGraphic.hpp>
32 : #include <cppuhelper/typeprovider.hxx>
33 :
34 : using namespace ::com::sun::star;
35 :
36 13 : static void ImplDrawDefault( OutputDevice* pOutDev, const OUString* pText,
37 : vcl::Font* pFont, const Bitmap* pBitmap, const BitmapEx* pBitmapEx,
38 : const Point& rDestPt, const Size& rDestSize )
39 : {
40 13 : sal_uInt16 nPixel = (sal_uInt16) pOutDev->PixelToLogic( Size( 1, 1 ) ).Width();
41 13 : sal_uInt16 nPixelWidth = nPixel;
42 13 : Point aPoint( rDestPt.X() + nPixelWidth, rDestPt.Y() + nPixelWidth );
43 13 : Size aSize( rDestSize.Width() - ( nPixelWidth << 1 ), rDestSize.Height() - ( nPixelWidth << 1 ) );
44 13 : bool bFilled = ( pBitmap != NULL || pBitmapEx != NULL || pFont != NULL );
45 13 : Rectangle aBorderRect( aPoint, aSize );
46 :
47 13 : pOutDev->Push();
48 :
49 13 : pOutDev->SetFillColor();
50 :
51 : // On the printer a black rectangle and on the screen one with 3D effect
52 13 : if ( pOutDev->GetOutDevType() == OUTDEV_PRINTER )
53 0 : pOutDev->SetLineColor( COL_BLACK );
54 : else
55 : {
56 13 : aBorderRect.Left() += nPixel;
57 13 : aBorderRect.Top() += nPixel;
58 :
59 13 : pOutDev->SetLineColor( COL_LIGHTGRAY );
60 13 : pOutDev->DrawRect( aBorderRect );
61 :
62 13 : aBorderRect.Left() -= nPixel;
63 13 : aBorderRect.Top() -= nPixel;
64 13 : aBorderRect.Right() -= nPixel;
65 13 : aBorderRect.Bottom() -= nPixel;
66 13 : pOutDev->SetLineColor( COL_GRAY );
67 : }
68 :
69 13 : pOutDev->DrawRect( aBorderRect );
70 :
71 13 : aPoint.X() += nPixelWidth + 2*nPixel;
72 13 : aPoint.Y() += nPixelWidth + 2*nPixel;
73 13 : aSize.Width() -= 2*nPixelWidth + 4*nPixel;
74 13 : aSize.Height() -= 2*nPixelWidth + 4*nPixel;
75 :
76 37 : if( aSize.Width() > 0 && aSize.Height() > 0
77 24 : && ( ( pBitmap && !!*pBitmap ) || ( pBitmapEx && !!*pBitmapEx ) ) )
78 : {
79 11 : Size aBitmapSize( pOutDev->PixelToLogic( pBitmap ? pBitmap->GetSizePixel() : pBitmapEx->GetSizePixel() ) );
80 :
81 11 : if( aSize.Height() > aBitmapSize.Height() && aSize.Width() > aBitmapSize.Width() )
82 : {
83 8 : if ( pBitmap )
84 0 : pOutDev->DrawBitmap( aPoint, *pBitmap );
85 : else
86 8 : pOutDev->DrawBitmapEx( aPoint, *pBitmapEx );
87 8 : aPoint.X() += aBitmapSize.Width() + 2*nPixel;
88 8 : aSize.Width() -= aBitmapSize.Width() + 2*nPixel;
89 : }
90 : }
91 :
92 37 : if ( aSize.Width() > 0 && aSize.Height() > 0 && pFont && pText && pText->getLength()
93 24 : && !(!pOutDev->IsOutputEnabled() /*&& pOutDev->GetConnectMetaFile() */) )
94 : {
95 11 : MapMode aMapMode( MAP_POINT );
96 11 : Size aSz = pOutDev->LogicToLogic( Size( 0, 12 ), &aMapMode, NULL );
97 11 : long nThreshold = aSz.Height() / 2;
98 11 : long nStep = nThreshold / 3;
99 :
100 11 : if ( !nStep )
101 0 : nStep = aSz.Height() - nThreshold;
102 :
103 12 : for(;; aSz.Height() -= nStep )
104 : {
105 23 : pFont->SetSize( aSz );
106 23 : pOutDev->SetFont( *pFont );
107 :
108 23 : long nTextHeight = pOutDev->GetTextHeight();
109 23 : long nTextWidth = pOutDev->GetTextWidth( *pText );
110 23 : if ( nTextHeight )
111 : {
112 : // The approximation does not respect imprecisions caused
113 : // by word wraps
114 23 : long nLines = aSize.Height() / nTextHeight;
115 23 : long nWidth = aSize.Width() * nLines; // Approximation!!!
116 :
117 23 : if ( nTextWidth <= nWidth || aSz.Height() <= nThreshold )
118 : {
119 11 : sal_uInt16 nStart = 0;
120 11 : sal_uInt16 nLen = 0;
121 :
122 22 : while( nStart < pText->getLength() && (*pText)[nStart] == ' ' )
123 0 : nStart++;
124 547 : while( nStart+nLen < pText->getLength() && (*pText)[nStart+nLen] != ' ' )
125 525 : nLen++;
126 33 : while( nStart < pText->getLength() && nLines-- )
127 : {
128 11 : sal_uInt16 nNext = nLen;
129 0 : do
130 : {
131 22 : while ( nStart+nNext < pText->getLength() && (*pText)[nStart+nNext] == ' ' )
132 0 : nNext++;
133 22 : while ( nStart+nNext < pText->getLength() && (*pText)[nStart+nNext] != ' ' )
134 0 : nNext++;
135 11 : nTextWidth = pOutDev->GetTextWidth( *pText, nStart, nNext );
136 11 : if ( nTextWidth > aSize.Width() )
137 11 : break;
138 0 : nLen = nNext;
139 : }
140 0 : while ( nStart+nNext < pText->getLength() );
141 :
142 11 : sal_uInt16 n = nLen;
143 11 : nTextWidth = pOutDev->GetTextWidth( *pText, nStart, n );
144 172 : while( nTextWidth > aSize.Width() )
145 150 : nTextWidth = pOutDev->GetTextWidth( *pText, nStart, --n );
146 11 : pOutDev->DrawText( aPoint, *pText, nStart, n );
147 :
148 11 : aPoint.Y() += nTextHeight;
149 11 : nStart = sal::static_int_cast<sal_uInt16>(nStart + nLen);
150 11 : nLen = nNext-nLen;
151 22 : while( nStart < pText->getLength() && (*pText)[nStart] == ' ' )
152 : {
153 0 : nStart++;
154 0 : nLen--;
155 : }
156 : }
157 11 : break;
158 : }
159 : }
160 : else
161 0 : break;
162 12 : }
163 : }
164 :
165 : // If the default graphic does not have content, we draw a red rectangle
166 13 : if( !bFilled )
167 : {
168 0 : aBorderRect.Left()++;
169 0 : aBorderRect.Top()++;
170 0 : aBorderRect.Right()--;
171 0 : aBorderRect.Bottom()--;
172 :
173 0 : pOutDev->SetLineColor( COL_LIGHTRED );
174 0 : pOutDev->DrawLine( aBorderRect.TopLeft(), aBorderRect.BottomRight() );
175 0 : pOutDev->DrawLine( aBorderRect.TopRight(), aBorderRect.BottomLeft() );
176 : }
177 :
178 13 : pOutDev->Pop();
179 13 : }
180 :
181 0 : TYPEINIT1_AUTOFACTORY( Graphic, SvDataCopyStream );
182 :
183 20939 : Graphic::Graphic()
184 : {
185 20939 : mpImpGraphic = new ImpGraphic;
186 20939 : }
187 :
188 105837 : Graphic::Graphic( const Graphic& rGraphic ) :
189 105837 : SvDataCopyStream()
190 : {
191 105837 : if( rGraphic.IsAnimated() )
192 0 : mpImpGraphic = new ImpGraphic( *rGraphic.mpImpGraphic );
193 : else
194 : {
195 105837 : mpImpGraphic = rGraphic.mpImpGraphic;
196 105837 : mpImpGraphic->mnRefCount++;
197 : }
198 105837 : }
199 :
200 758 : Graphic::Graphic( const Bitmap& rBmp )
201 : {
202 758 : mpImpGraphic = new ImpGraphic( rBmp );
203 758 : }
204 :
205 193573 : Graphic::Graphic( const BitmapEx& rBmpEx )
206 : {
207 193573 : mpImpGraphic = new ImpGraphic( rBmpEx );
208 193573 : }
209 :
210 296 : Graphic::Graphic(const SvgDataPtr& rSvgDataPtr)
211 : {
212 296 : mpImpGraphic = new ImpGraphic(rSvgDataPtr);
213 296 : }
214 :
215 12 : Graphic::Graphic( const Animation& rAnimation )
216 : {
217 12 : mpImpGraphic = new ImpGraphic( rAnimation );
218 12 : }
219 :
220 1938 : Graphic::Graphic( const GDIMetaFile& rMtf )
221 : {
222 1938 : mpImpGraphic = new ImpGraphic( rMtf );
223 1938 : }
224 :
225 185977 : Graphic::Graphic( const ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic >& rxGraphic )
226 : {
227 185977 : uno::Reference< lang::XUnoTunnel > xTunnel( rxGraphic, uno::UNO_QUERY );
228 185977 : const ::Graphic* pGraphic = ( xTunnel.is() ?
229 427447 : reinterpret_cast< ::Graphic* >( xTunnel->getSomething( getUnoTunnelId() ) ) :
230 452444 : NULL );
231 :
232 185977 : if( pGraphic )
233 : {
234 80490 : if( pGraphic->IsAnimated() )
235 0 : mpImpGraphic = new ImpGraphic( *pGraphic->mpImpGraphic );
236 : else
237 : {
238 80490 : mpImpGraphic = pGraphic->mpImpGraphic;
239 80490 : mpImpGraphic->mnRefCount++;
240 : }
241 : }
242 : else
243 105487 : mpImpGraphic = new ImpGraphic;
244 185977 : }
245 :
246 1104409 : Graphic::~Graphic()
247 : {
248 509151 : if( mpImpGraphic->mnRefCount == 1UL )
249 328031 : delete mpImpGraphic;
250 : else
251 181120 : mpImpGraphic->mnRefCount--;
252 595258 : }
253 :
254 76401 : void Graphic::ImplTestRefCount()
255 : {
256 76401 : if( mpImpGraphic->mnRefCount > 1UL )
257 : {
258 13943 : mpImpGraphic->mnRefCount--;
259 13943 : mpImpGraphic = new ImpGraphic( *mpImpGraphic );
260 : }
261 76401 : }
262 :
263 15573 : Graphic& Graphic::operator=( const Graphic& rGraphic )
264 : {
265 15573 : if( &rGraphic != this )
266 : {
267 15573 : if( rGraphic.IsAnimated() )
268 : {
269 12 : if( mpImpGraphic->mnRefCount == 1UL )
270 12 : delete mpImpGraphic;
271 : else
272 0 : mpImpGraphic->mnRefCount--;
273 :
274 12 : mpImpGraphic = new ImpGraphic( *rGraphic.mpImpGraphic );
275 : }
276 : else
277 : {
278 15561 : rGraphic.mpImpGraphic->mnRefCount++;
279 :
280 15561 : if( mpImpGraphic->mnRefCount == 1UL )
281 8739 : delete mpImpGraphic;
282 : else
283 6822 : mpImpGraphic->mnRefCount--;
284 :
285 15561 : mpImpGraphic = rGraphic.mpImpGraphic;
286 : }
287 : }
288 :
289 15573 : return *this;
290 : }
291 :
292 10363 : bool Graphic::operator==( const Graphic& rGraphic ) const
293 : {
294 10363 : return( *mpImpGraphic == *rGraphic.mpImpGraphic );
295 : }
296 :
297 0 : bool Graphic::operator!=( const Graphic& rGraphic ) const
298 : {
299 0 : return( *mpImpGraphic != *rGraphic.mpImpGraphic );
300 : }
301 :
302 0 : bool Graphic::operator!() const
303 : {
304 0 : return( GRAPHIC_NONE == mpImpGraphic->ImplGetType() );
305 : }
306 :
307 0 : void Graphic::Load( SvStream& rIStm )
308 : {
309 0 : ReadGraphic( rIStm, *this );
310 0 : }
311 :
312 0 : void Graphic::Save( SvStream& rOStm )
313 : {
314 0 : WriteGraphic( rOStm, *this );
315 0 : }
316 :
317 0 : void Graphic::Assign( const SvDataCopyStream& rCopyStream )
318 : {
319 0 : *this = static_cast<const Graphic&>( rCopyStream );
320 0 : }
321 :
322 69 : void Graphic::Clear()
323 : {
324 69 : ImplTestRefCount();
325 69 : mpImpGraphic->ImplClear();
326 69 : }
327 :
328 283544 : GraphicType Graphic::GetType() const
329 : {
330 283544 : return mpImpGraphic->ImplGetType();
331 : }
332 :
333 43 : void Graphic::SetDefaultType()
334 : {
335 43 : ImplTestRefCount();
336 43 : mpImpGraphic->ImplSetDefaultType();
337 43 : }
338 :
339 2371 : bool Graphic::IsSupportedGraphic() const
340 : {
341 2371 : return mpImpGraphic->ImplIsSupportedGraphic();
342 : }
343 :
344 25440 : bool Graphic::IsTransparent() const
345 : {
346 25440 : return mpImpGraphic->ImplIsTransparent();
347 : }
348 :
349 25438 : bool Graphic::IsAlpha() const
350 : {
351 25438 : return mpImpGraphic->ImplIsAlpha();
352 : }
353 :
354 232331 : bool Graphic::IsAnimated() const
355 : {
356 232331 : return mpImpGraphic->ImplIsAnimated();
357 : }
358 :
359 25143 : bool Graphic::IsEPS() const
360 : {
361 25143 : return mpImpGraphic->ImplIsEPS();
362 : }
363 :
364 6 : Bitmap Graphic::GetBitmap(const GraphicConversionParameters& rParameters) const
365 : {
366 6 : return mpImpGraphic->ImplGetBitmap(rParameters);
367 : }
368 :
369 191505 : BitmapEx Graphic::GetBitmapEx(const GraphicConversionParameters& rParameters) const
370 : {
371 191505 : return mpImpGraphic->ImplGetBitmapEx(rParameters);
372 : }
373 :
374 0 : Animation Graphic::GetAnimation() const
375 : {
376 0 : return mpImpGraphic->ImplGetAnimation();
377 : }
378 :
379 1478 : const GDIMetaFile& Graphic::GetGDIMetaFile() const
380 : {
381 1478 : return mpImpGraphic->ImplGetGDIMetaFile();
382 : }
383 :
384 186370 : uno::Reference< graphic::XGraphic > Graphic::GetXGraphic() const
385 : {
386 186370 : uno::Reference< graphic::XGraphic > xRet;
387 :
388 186370 : if( GetType() != GRAPHIC_NONE )
389 : {
390 79930 : uno::Reference < uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
391 159857 : uno::Reference< graphic::XGraphicProvider > xProv( graphic::GraphicProvider::create( xContext ) );
392 :
393 159854 : uno::Sequence< beans::PropertyValue > aLoadProps( 1 );
394 159854 : OUString aURL = "private:memorygraphic/" + OUString::number( reinterpret_cast< sal_Int64 >( this ) );
395 :
396 79927 : aLoadProps[ 0 ].Name = "URL";
397 79927 : aLoadProps[ 0 ].Value <<= aURL;
398 :
399 159857 : xRet = xProv->queryGraphic( aLoadProps );
400 : }
401 :
402 186367 : return xRet;
403 : }
404 :
405 37731 : Size Graphic::GetPrefSize() const
406 : {
407 37731 : return mpImpGraphic->ImplGetPrefSize();
408 : }
409 :
410 5945 : void Graphic::SetPrefSize( const Size& rPrefSize )
411 : {
412 5945 : ImplTestRefCount();
413 5945 : mpImpGraphic->ImplSetPrefSize( rPrefSize );
414 5945 : }
415 :
416 36587 : MapMode Graphic::GetPrefMapMode() const
417 : {
418 36587 : return mpImpGraphic->ImplGetPrefMapMode();
419 : }
420 :
421 5945 : void Graphic::SetPrefMapMode( const MapMode& rPrefMapMode )
422 : {
423 5945 : ImplTestRefCount();
424 5945 : mpImpGraphic->ImplSetPrefMapMode( rPrefMapMode );
425 5945 : }
426 :
427 405 : Size Graphic::GetSizePixel( const OutputDevice* pRefDevice ) const
428 : {
429 405 : Size aRet;
430 :
431 405 : if( GRAPHIC_BITMAP == mpImpGraphic->ImplGetType() )
432 398 : aRet = mpImpGraphic->ImplGetBitmapEx(GraphicConversionParameters()).GetSizePixel();
433 : else
434 7 : aRet = ( pRefDevice ? pRefDevice : Application::GetDefaultDevice() )->LogicToPixel( GetPrefSize(), GetPrefMapMode() );
435 :
436 405 : return aRet;
437 : }
438 :
439 71770 : sal_uLong Graphic::GetSizeBytes() const
440 : {
441 71770 : return mpImpGraphic->ImplGetSizeBytes();
442 : }
443 :
444 0 : void Graphic::Draw( OutputDevice* pOutDev, const Point& rDestPt ) const
445 : {
446 0 : mpImpGraphic->ImplDraw( pOutDev, rDestPt );
447 0 : }
448 :
449 59 : void Graphic::Draw( OutputDevice* pOutDev,
450 : const Point& rDestPt, const Size& rDestSz ) const
451 : {
452 59 : if( GRAPHIC_DEFAULT == mpImpGraphic->ImplGetType() )
453 0 : ImplDrawDefault( pOutDev, NULL, NULL, NULL, NULL, rDestPt, rDestSz );
454 : else
455 59 : mpImpGraphic->ImplDraw( pOutDev, rDestPt, rDestSz );
456 59 : }
457 :
458 13 : void Graphic::DrawEx( OutputDevice* pOutDev, const OUString& rText,
459 : vcl::Font& rFont, const BitmapEx& rBitmap,
460 : const Point& rDestPt, const Size& rDestSz )
461 : {
462 13 : ImplDrawDefault( pOutDev, &rText, &rFont, NULL, &rBitmap, rDestPt, rDestSz );
463 13 : }
464 :
465 0 : void Graphic::StartAnimation( OutputDevice* pOutDev, const Point& rDestPt,
466 : const Size& rDestSz, long nExtraData,
467 : OutputDevice* pFirstFrameOutDev )
468 : {
469 0 : ImplTestRefCount();
470 0 : mpImpGraphic->ImplStartAnimation( pOutDev, rDestPt, rDestSz, nExtraData, pFirstFrameOutDev );
471 0 : }
472 :
473 0 : void Graphic::StopAnimation( OutputDevice* pOutDev, long nExtraData )
474 : {
475 0 : ImplTestRefCount();
476 0 : mpImpGraphic->ImplStopAnimation( pOutDev, nExtraData );
477 0 : }
478 :
479 5685 : void Graphic::SetAnimationNotifyHdl( const Link<>& rLink )
480 : {
481 5685 : mpImpGraphic->ImplSetAnimationNotifyHdl( rLink );
482 5685 : }
483 :
484 7623 : Link<> Graphic::GetAnimationNotifyHdl() const
485 : {
486 7623 : return mpImpGraphic->ImplGetAnimationNotifyHdl();
487 : }
488 :
489 0 : sal_uLong Graphic::GetAnimationLoopCount() const
490 : {
491 0 : return mpImpGraphic->ImplGetAnimationLoopCount();
492 : }
493 :
494 11807 : GraphicReader* Graphic::GetContext()
495 : {
496 11807 : return mpImpGraphic->ImplGetContext();
497 : }
498 :
499 645 : void Graphic::SetContext( GraphicReader* pReader )
500 : {
501 645 : mpImpGraphic->ImplSetContext( pReader );
502 645 : }
503 :
504 229 : bool Graphic::SwapOut()
505 : {
506 229 : ImplTestRefCount();
507 229 : return mpImpGraphic->ImplSwapOut();
508 : }
509 :
510 1 : void Graphic::SwapOutAsLink()
511 : {
512 1 : ImplTestRefCount();
513 1 : mpImpGraphic->ImplSwapOutAsLink();
514 1 : }
515 :
516 0 : bool Graphic::SwapOut( SvStream* pOStream )
517 : {
518 0 : ImplTestRefCount();
519 0 : return mpImpGraphic->ImplSwapOut( pOStream );
520 : }
521 :
522 51179 : bool Graphic::SwapIn()
523 : {
524 51179 : ImplTestRefCount();
525 51179 : return mpImpGraphic->ImplSwapIn();
526 : }
527 :
528 0 : bool Graphic::SwapIn( SvStream* pStrm )
529 : {
530 0 : ImplTestRefCount();
531 0 : return mpImpGraphic->ImplSwapIn( pStrm );
532 : }
533 :
534 90109 : bool Graphic::IsSwapOut() const
535 : {
536 90109 : return mpImpGraphic->ImplIsSwapOut();
537 : }
538 :
539 7954 : void Graphic::SetLink( const GfxLink& rGfxLink )
540 : {
541 7954 : ImplTestRefCount();
542 7954 : mpImpGraphic->ImplSetLink( rGfxLink );
543 7954 : }
544 :
545 1569 : GfxLink Graphic::GetLink() const
546 : {
547 1569 : return mpImpGraphic->ImplGetLink();
548 : }
549 :
550 30228 : bool Graphic::IsLink() const
551 : {
552 30228 : return mpImpGraphic->ImplIsLink();
553 : }
554 :
555 3977 : sal_uLong Graphic::GetChecksum() const
556 : {
557 3977 : return mpImpGraphic->ImplGetChecksum();
558 : }
559 :
560 353 : bool Graphic::ExportNative( SvStream& rOStream ) const
561 : {
562 353 : return mpImpGraphic->ImplExportNative( rOStream );
563 : }
564 :
565 5036 : SvStream& ReadGraphic( SvStream& rIStream, Graphic& rGraphic )
566 : {
567 5036 : rGraphic.ImplTestRefCount();
568 5036 : return ReadImpGraphic( rIStream, *rGraphic.mpImpGraphic );
569 : }
570 :
571 116 : SvStream& WriteGraphic( SvStream& rOStream, const Graphic& rGraphic )
572 : {
573 116 : return WriteImpGraphic( rOStream, *rGraphic.mpImpGraphic );
574 : }
575 :
576 7191 : const SvgDataPtr& Graphic::getSvgData() const
577 : {
578 7191 : return mpImpGraphic->getSvgData();
579 : }
580 :
581 : namespace {
582 :
583 : struct Id: public rtl::Static<cppu::OImplementationId, Id> {};
584 :
585 : }
586 :
587 160990 : css::uno::Sequence<sal_Int8> Graphic::getUnoTunnelId() {
588 160990 : return Id::get().getImplementationId();
589 : }
590 :
591 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|