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