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 <tools/debug.hxx>
21 : #include <tools/poly.hxx>
22 :
23 : #include <vcl/svapp.hxx>
24 : #include <vcl/ctrl.hxx>
25 : #include <vcl/region.hxx>
26 : #include <vcl/virdev.hxx>
27 : #include <vcl/window.hxx>
28 : #include <vcl/metaact.hxx>
29 : #include <vcl/gdimtf.hxx>
30 : #include <vcl/print.hxx>
31 : #include <vcl/outdev.hxx>
32 : #include <vcl/unowrap.hxx>
33 : #include <vcl/settings.hxx>
34 : #include <vcl/sysdata.hxx>
35 :
36 : #include <vcl/outdevstate.hxx>
37 :
38 : #include <salgdi.hxx>
39 : #include <sallayout.hxx>
40 : #include <salframe.hxx>
41 : #include <salvd.hxx>
42 : #include <salprn.hxx>
43 : #include <svdata.hxx>
44 : #include <window.h>
45 : #include <outdev.h>
46 : #include <outdata.hxx>
47 : #include <outdevstatestack.hxx>
48 :
49 : #include "PhysicalFontCollection.hxx"
50 :
51 : #include <basegfx/point/b2dpoint.hxx>
52 : #include <basegfx/vector/b2dvector.hxx>
53 : #include <basegfx/polygon/b2dpolygon.hxx>
54 : #include <basegfx/polygon/b2dpolypolygon.hxx>
55 : #include <basegfx/matrix/b2dhommatrix.hxx>
56 : #include <basegfx/polygon/b2dpolygontools.hxx>
57 : #include <basegfx/polygon/b2dpolypolygontools.hxx>
58 : #include <basegfx/polygon/b2dlinegeometry.hxx>
59 :
60 : #include <com/sun/star/awt/XGraphics.hpp>
61 : #include <com/sun/star/uno/Sequence.hxx>
62 : #include <com/sun/star/rendering/XCanvas.hpp>
63 : #include <com/sun/star/rendering/CanvasFactory.hpp>
64 : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
65 : #include <comphelper/processfactory.hxx>
66 :
67 : #include <config_cairo_canvas.h>
68 :
69 : #include <numeric>
70 : #include <stack>
71 :
72 : #ifdef DISABLE_DYNLOADING
73 : // Linking all needed LO code into one .so/executable, these already
74 : // exist in the tools library, so put them in the anonymous namespace
75 : // here to avoid clash...
76 : namespace {
77 : #endif
78 : #ifdef DISABLE_DYNLOADING
79 : }
80 : #endif
81 :
82 : // Begin initializer and accessor public functions
83 :
84 422350 : OutputDevice::OutputDevice() :
85 : mnRefCnt(1), // cf. VclPtrInstance and README.lifecycle
86 : maRegion(true),
87 : maFillColor( COL_WHITE ),
88 : maTextLineColor( COL_TRANSPARENT ),
89 422350 : mxSettings( new AllSettings(Application::GetSettings()) )
90 : {
91 422350 : mpGraphics = NULL;
92 422350 : mpUnoGraphicsList = NULL;
93 422350 : mpPrevGraphics = NULL;
94 422350 : mpNextGraphics = NULL;
95 422350 : mpMetaFile = NULL;
96 422350 : mpFontEntry = NULL;
97 422350 : mpFontCache = NULL;
98 422350 : mpFontCollection = NULL;
99 422350 : mpGetDevFontList = NULL;
100 422350 : mpGetDevSizeList = NULL;
101 422350 : mpOutDevStateStack = new OutDevStateStack;
102 422350 : mpPDFWriter = NULL;
103 422350 : mpAlphaVDev = NULL;
104 422350 : mpExtOutDevData = NULL;
105 422350 : mnOutOffX = 0;
106 422350 : mnOutOffY = 0;
107 422350 : mnOutWidth = 0;
108 422350 : mnOutHeight = 0;
109 422350 : mnDPIX = 0;
110 422350 : mnDPIY = 0;
111 422350 : mnDPIScaleFactor = 1;
112 422350 : mnTextOffX = 0;
113 422350 : mnTextOffY = 0;
114 422350 : mnOutOffOrigX = 0;
115 422350 : mnOutOffLogicX = 0;
116 422350 : mnOutOffOrigY = 0;
117 422350 : mnOutOffLogicY = 0;
118 422350 : mnEmphasisAscent = 0;
119 422350 : mnEmphasisDescent = 0;
120 422350 : mnDrawMode = DrawModeFlags::Default;
121 422350 : mnTextLayoutMode = TEXT_LAYOUT_DEFAULT;
122 :
123 422350 : if( AllSettings::GetLayoutRTL() ) //#i84553# tip BiDi preference to RTL
124 0 : mnTextLayoutMode = TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_TEXTORIGIN_LEFT;
125 :
126 422350 : meOutDevType = OUTDEV_DONTKNOW;
127 422350 : meOutDevViewType = OUTDEV_VIEWTYPE_DONTKNOW;
128 422350 : mbMap = false;
129 422350 : mbMapIsDefault = true;
130 422350 : mbClipRegion = false;
131 422350 : mbBackground = false;
132 422350 : mbOutput = true;
133 422350 : mbDevOutput = false;
134 422350 : mbOutputClipped = false;
135 422350 : maTextColor = Color( COL_BLACK );
136 422350 : maOverlineColor = Color( COL_TRANSPARENT );
137 422350 : meTextAlign = maFont.GetAlign();
138 422350 : meRasterOp = ROP_OVERPAINT;
139 422350 : mnAntialiasing = AntialiasingFlags::NONE;
140 422350 : meTextLanguage = 0; // TODO: get default from configuration?
141 422350 : mbLineColor = true;
142 422350 : mbFillColor = true;
143 422350 : mbInitLineColor = true;
144 422350 : mbInitFillColor = true;
145 422350 : mbInitFont = true;
146 422350 : mbInitTextColor = true;
147 422350 : mbInitClipRegion = true;
148 422350 : mbClipRegionSet = false;
149 422350 : mbKerning = false;
150 422350 : mbNewFont = true;
151 422350 : mbTextLines = false;
152 422350 : mbTextBackground = false;
153 422350 : mbTextSpecial = false;
154 422350 : mbRefPoint = false;
155 422350 : mbEnableRTL = false; // mirroring must be explicitly allowed (typically for windows only)
156 :
157 : // struct ImplMapRes
158 422350 : maMapRes.mnMapOfsX = 0;
159 422350 : maMapRes.mnMapOfsY = 0;
160 422350 : maMapRes.mnMapScNumX = 1;
161 422350 : maMapRes.mnMapScNumY = 1;
162 422350 : maMapRes.mnMapScDenomX = 1;
163 422350 : maMapRes.mnMapScDenomY = 1;
164 422350 : maMapRes.mfOffsetX = 0.0;
165 422350 : maMapRes.mfOffsetY = 0.0;
166 422350 : maMapRes.mfScaleX = 1.0;
167 422350 : maMapRes.mfScaleY = 1.0;
168 : // struct ImplThresholdRes
169 422350 : maThresRes.mnThresLogToPixX = 0;
170 422350 : maThresRes.mnThresLogToPixY = 0;
171 422350 : maThresRes.mnThresPixToLogX = 0;
172 422350 : maThresRes.mnThresPixToLogY = 0;
173 :
174 : // struct ImplOutDevData- see #i82615#
175 422350 : mpOutDevData = new ImplOutDevData;
176 422350 : mpOutDevData->mpRotateDev = NULL;
177 422350 : mpOutDevData->mpRecordLayout = NULL;
178 :
179 : // #i75163#
180 422350 : mpOutDevData->mpViewTransform = NULL;
181 422350 : mpOutDevData->mpInverseViewTransform = NULL;
182 :
183 422350 : mbDisposed = false;
184 422350 : }
185 :
186 820512 : OutputDevice::~OutputDevice()
187 : {
188 410256 : disposeOnce();
189 410256 : }
190 :
191 1688146 : void OutputDevice::disposeOnce()
192 : {
193 1688146 : if ( mbDisposed )
194 2956939 : return;
195 419353 : mbDisposed = true;
196 :
197 : // catch badness where our OutputDevice sub-class was not
198 : // wrapped safely in a VclPtr cosily.
199 : // FIXME: as/when we make our destructors all protected,
200 : // we should introduce this assert:
201 : // assert( mnRefCnt > 0 );
202 :
203 419353 : dispose();
204 : }
205 :
206 419353 : void OutputDevice::dispose()
207 : {
208 419353 : if ( GetUnoGraphicsList() )
209 : {
210 760 : UnoWrapperBase* pWrapper = Application::GetUnoWrapper( false );
211 760 : if ( pWrapper )
212 760 : pWrapper->ReleaseAllGraphics( this );
213 760 : delete mpUnoGraphicsList;
214 760 : mpUnoGraphicsList = NULL;
215 : }
216 :
217 419353 : mpOutDevData->mpRotateDev.disposeAndClear();
218 :
219 : // #i75163#
220 419353 : ImplInvalidateViewTransform();
221 :
222 419353 : delete mpOutDevData;
223 419353 : mpOutDevData = NULL;
224 :
225 : // for some reason, we haven't removed state from the stack properly
226 419353 : if ( !mpOutDevStateStack->empty() )
227 : {
228 : SAL_WARN( "vcl.gdi", "OutputDevice::~OutputDevice(): OutputDevice::Push() calls != OutputDevice::Pop() calls" );
229 0 : while ( !mpOutDevStateStack->empty() )
230 : {
231 0 : mpOutDevStateStack->pop_back();
232 : }
233 : }
234 419353 : delete mpOutDevStateStack;
235 419353 : mpOutDevStateStack = NULL;
236 :
237 : // release the active font instance
238 419353 : if( mpFontEntry )
239 55 : mpFontCache->Release( mpFontEntry );
240 :
241 : // remove cached results of GetDevFontList/GetDevSizeList
242 : // TODO: use smart pointers for them
243 419353 : delete mpGetDevFontList;
244 419353 : mpGetDevFontList = NULL;
245 :
246 419353 : delete mpGetDevSizeList;
247 419353 : mpGetDevSizeList = NULL;
248 :
249 : // release ImplFontCache specific to this OutputDevice
250 : // TODO: refcount ImplFontCache
251 419353 : if( mpFontCache
252 418926 : && (mpFontCache != ImplGetSVData()->maGDIData.mpScreenFontCache)
253 422955 : && (ImplGetSVData()->maGDIData.mpScreenFontCache != NULL) )
254 : {
255 3602 : delete mpFontCache;
256 3602 : mpFontCache = NULL;
257 : }
258 :
259 : // release ImplFontList specific to this OutputDevice
260 : // TODO: refcount ImplFontList
261 419353 : if( mpFontCollection
262 419350 : && (mpFontCollection != ImplGetSVData()->maGDIData.mpScreenFontList)
263 423379 : && (ImplGetSVData()->maGDIData.mpScreenFontList != NULL) )
264 : {
265 4026 : mpFontCollection->Clear();
266 4026 : delete mpFontCollection;
267 4026 : mpFontCollection = NULL;
268 : }
269 :
270 419353 : mpAlphaVDev.disposeAndClear();
271 419353 : }
272 :
273 213 : SalGraphics* OutputDevice::GetGraphics()
274 : {
275 : DBG_TESTSOLARMUTEX();
276 :
277 213 : if ( !mpGraphics )
278 : {
279 213 : if ( !AcquireGraphics() )
280 : {
281 : SAL_WARN("vcl", "No mpGraphics set");
282 : }
283 : }
284 :
285 213 : return mpGraphics;
286 : }
287 :
288 0 : SalGraphics const *OutputDevice::GetGraphics() const
289 : {
290 : DBG_TESTSOLARMUTEX();
291 :
292 0 : if ( !mpGraphics )
293 : {
294 0 : if ( !AcquireGraphics() )
295 : {
296 : SAL_WARN("vcl", "No mpGraphics set");
297 : }
298 : }
299 :
300 0 : return mpGraphics;
301 : }
302 :
303 46410 : void OutputDevice::SetConnectMetaFile( GDIMetaFile* pMtf )
304 : {
305 46410 : mpMetaFile = pMtf;
306 46410 : }
307 :
308 346718 : void OutputDevice::SetSettings( const AllSettings& rSettings )
309 : {
310 346718 : *mxSettings = rSettings;
311 :
312 346718 : if( mpAlphaVDev )
313 10 : mpAlphaVDev->SetSettings( rSettings );
314 346718 : }
315 :
316 87 : SystemGraphicsData OutputDevice::GetSystemGfxData() const
317 : {
318 87 : if ( !mpGraphics )
319 : {
320 1 : if ( !AcquireGraphics() )
321 0 : return SystemGraphicsData();
322 : }
323 :
324 87 : return mpGraphics->GetGraphicsData();
325 : }
326 :
327 3 : bool OutputDevice::SupportsCairo() const
328 : {
329 : #if ENABLE_CAIRO_CANVAS
330 3 : if (!mpGraphics)
331 : {
332 0 : if (!AcquireGraphics())
333 0 : return false;
334 : }
335 :
336 3 : return mpGraphics->SupportsCairo();
337 : #else
338 : (void) this; // loplugin:staticmethods
339 : return false;
340 : #endif
341 : }
342 :
343 2 : cairo::SurfaceSharedPtr OutputDevice::CreateSurface(const cairo::CairoSurfaceSharedPtr& rSurface) const
344 : {
345 2 : if (!mpGraphics)
346 : {
347 0 : if (!AcquireGraphics())
348 0 : return cairo::SurfaceSharedPtr();
349 : }
350 2 : return mpGraphics->CreateSurface(rSurface);
351 : }
352 :
353 2 : cairo::SurfaceSharedPtr OutputDevice::CreateSurface(int x, int y, int width, int height) const
354 : {
355 2 : if (!mpGraphics)
356 : {
357 0 : if (!AcquireGraphics())
358 0 : return cairo::SurfaceSharedPtr();
359 : }
360 2 : return mpGraphics->CreateSurface(*this, x, y, width, height);
361 : }
362 :
363 0 : cairo::SurfaceSharedPtr OutputDevice::CreateBitmapSurface(const BitmapSystemData& rData, const Size& rSize) const
364 : {
365 0 : if (!mpGraphics)
366 : {
367 0 : if (!AcquireGraphics())
368 0 : return cairo::SurfaceSharedPtr();
369 : }
370 0 : return mpGraphics->CreateBitmapSurface(*this, rData, rSize);
371 : }
372 :
373 0 : css::uno::Any OutputDevice::GetNativeSurfaceHandle(cairo::SurfaceSharedPtr& rSurface, const ::basegfx::B2ISize& rSize) const
374 : {
375 0 : if (!mpGraphics)
376 : {
377 0 : if (!AcquireGraphics())
378 0 : return css::uno::Any();
379 : }
380 0 : return mpGraphics->GetNativeSurfaceHandle(rSurface, rSize);
381 : }
382 :
383 87 : css::uno::Any OutputDevice::GetSystemGfxDataAny() const
384 : {
385 87 : const SystemGraphicsData aSysData = GetSystemGfxData();
386 : css::uno::Sequence< sal_Int8 > aSeq( reinterpret_cast<sal_Int8 const *>(&aSysData),
387 87 : aSysData.nSize );
388 :
389 87 : return css::uno::makeAny(aSeq);
390 : }
391 :
392 128234 : void OutputDevice::SetRefPoint()
393 : {
394 :
395 128234 : if ( mpMetaFile )
396 12783 : mpMetaFile->AddAction( new MetaRefPointAction( Point(), false ) );
397 :
398 128234 : mbRefPoint = false;
399 128234 : maRefPoint.X() = maRefPoint.Y() = 0L;
400 :
401 128234 : if( mpAlphaVDev )
402 25670 : mpAlphaVDev->SetRefPoint();
403 128234 : }
404 :
405 27 : void OutputDevice::SetRefPoint( const Point& rRefPoint )
406 : {
407 :
408 27 : if ( mpMetaFile )
409 9 : mpMetaFile->AddAction( new MetaRefPointAction( rRefPoint, true ) );
410 :
411 27 : mbRefPoint = true;
412 27 : maRefPoint = rRefPoint;
413 :
414 27 : if( mpAlphaVDev )
415 0 : mpAlphaVDev->SetRefPoint( rRefPoint );
416 27 : }
417 :
418 229019 : sal_uInt16 OutputDevice::GetBitCount() const
419 : {
420 : // we need a graphics instance
421 229019 : if ( !mpGraphics )
422 : {
423 7 : if ( !AcquireGraphics() )
424 0 : return 0;
425 : }
426 :
427 229019 : return (sal_uInt16)mpGraphics->GetBitCount();
428 : }
429 :
430 305 : sal_uLong OutputDevice::GetColorCount() const
431 : {
432 :
433 305 : const sal_uInt16 nBitCount = GetBitCount();
434 305 : return( ( nBitCount > 31 ) ? ULONG_MAX : ( ( (sal_uLong) 1 ) << nBitCount) );
435 : }
436 :
437 0 : css::uno::Reference< css::rendering::XCanvas > OutputDevice::GetCanvas() const
438 : {
439 0 : css::uno::Sequence< css::uno::Any > aArg(6);
440 :
441 0 : aArg[ 0 ] = css::uno::makeAny( reinterpret_cast<sal_Int64>(this) );
442 0 : aArg[ 2 ] = css::uno::makeAny( css::awt::Rectangle( mnOutOffX, mnOutOffY, mnOutWidth, mnOutHeight ) );
443 0 : aArg[ 3 ] = css::uno::makeAny( sal_False );
444 0 : aArg[ 5 ] = GetSystemGfxDataAny();
445 :
446 0 : css::uno::Reference<css::uno::XComponentContext> xContext = comphelper::getProcessComponentContext();
447 :
448 : // Create canvas instance with window handle
449 0 : static css::uno::Reference<css::lang::XMultiComponentFactory > xCanvasFactory( css::rendering::CanvasFactory::create( xContext ) );
450 :
451 0 : css::uno::Reference<css::rendering::XCanvas> xCanvas;
452 : xCanvas.set(
453 0 : xCanvasFactory->createInstanceWithArgumentsAndContext(
454 0 : "com.sun.star.rendering.Canvas", aArg, xContext ),
455 0 : css::uno::UNO_QUERY );
456 :
457 0 : return xCanvas;
458 : }
459 :
460 28505 : css::uno::Reference< css::awt::XGraphics > OutputDevice::CreateUnoGraphics()
461 : {
462 28505 : UnoWrapperBase* pWrapper = Application::GetUnoWrapper();
463 28505 : return pWrapper ? pWrapper->CreateGraphics( this ) : css::uno::Reference< css::awt::XGraphics >();
464 : }
465 :
466 760 : std::vector< VCLXGraphics* > *OutputDevice::CreateUnoGraphicsList()
467 : {
468 760 : mpUnoGraphicsList = new std::vector< VCLXGraphics* >();
469 760 : return mpUnoGraphicsList;
470 : }
471 :
472 : // Helper public function
473 :
474 14542 : bool OutputDevice::SupportsOperation( OutDevSupportType eType ) const
475 : {
476 14542 : if( !mpGraphics )
477 0 : if( !AcquireGraphics() )
478 0 : return false;
479 14542 : const bool bHasSupport = mpGraphics->supportsOperation( eType );
480 14542 : return bHasSupport;
481 : }
482 :
483 : // Direct OutputDevice drawing public functions
484 :
485 367 : void OutputDevice::DrawOutDev( const Point& rDestPt, const Size& rDestSize,
486 : const Point& rSrcPt, const Size& rSrcSize )
487 : {
488 367 : if( ImplIsRecordLayout() )
489 0 : return;
490 :
491 367 : if ( ROP_INVERT == meRasterOp )
492 : {
493 0 : DrawRect( Rectangle( rDestPt, rDestSize ) );
494 0 : return;
495 : }
496 :
497 367 : if ( mpMetaFile )
498 : {
499 0 : const Bitmap aBmp( GetBitmap( rSrcPt, rSrcSize ) );
500 0 : mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) );
501 : }
502 :
503 367 : if ( !IsDeviceOutputNecessary() )
504 0 : return;
505 :
506 367 : if ( !mpGraphics )
507 24 : if ( !AcquireGraphics() )
508 0 : return;
509 :
510 367 : if ( mbInitClipRegion )
511 24 : InitClipRegion();
512 :
513 367 : if ( mbOutputClipped )
514 0 : return;
515 :
516 367 : long nSrcWidth = ImplLogicWidthToDevicePixel( rSrcSize.Width() );
517 367 : long nSrcHeight = ImplLogicHeightToDevicePixel( rSrcSize.Height() );
518 367 : long nDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
519 367 : long nDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
520 :
521 367 : if (nSrcWidth && nSrcHeight && nDestWidth && nDestHeight)
522 : {
523 : SalTwoRect aPosAry(ImplLogicXToDevicePixel(rSrcPt.X()), ImplLogicYToDevicePixel(rSrcPt.Y()),
524 : nSrcWidth, nSrcHeight,
525 : ImplLogicXToDevicePixel(rDestPt.X()), ImplLogicYToDevicePixel(rDestPt.Y()),
526 366 : nDestWidth, nDestHeight);
527 :
528 : const Rectangle aSrcOutRect( Point( mnOutOffX, mnOutOffY ),
529 366 : Size( mnOutWidth, mnOutHeight ) );
530 :
531 366 : AdjustTwoRect( aPosAry, aSrcOutRect );
532 :
533 366 : if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
534 366 : mpGraphics->CopyBits( aPosAry, NULL, this, NULL );
535 : }
536 :
537 367 : if( mpAlphaVDev )
538 0 : mpAlphaVDev->DrawOutDev( rDestPt, rDestSize, rSrcPt, rSrcSize );
539 : }
540 :
541 93579 : void OutputDevice::DrawOutDev( const Point& rDestPt, const Size& rDestSize,
542 : const Point& rSrcPt, const Size& rSrcSize,
543 : const OutputDevice& rOutDev )
544 : {
545 93579 : if ( ImplIsRecordLayout() )
546 503 : return;
547 :
548 93579 : if ( ROP_INVERT == meRasterOp )
549 : {
550 0 : DrawRect( Rectangle( rDestPt, rDestSize ) );
551 0 : return;
552 : }
553 :
554 93579 : if ( mpMetaFile )
555 : {
556 0 : const Bitmap aBmp( rOutDev.GetBitmap( rSrcPt, rSrcSize ) );
557 0 : mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) );
558 : }
559 :
560 93579 : if ( !IsDeviceOutputNecessary() )
561 495 : return;
562 :
563 93084 : if ( !mpGraphics )
564 2431 : if ( !AcquireGraphics() )
565 0 : return;
566 :
567 93084 : if ( mbInitClipRegion )
568 15969 : InitClipRegion();
569 :
570 93084 : if ( mbOutputClipped )
571 8 : return;
572 :
573 : SalTwoRect aPosAry(rOutDev.ImplLogicXToDevicePixel(rSrcPt.X()),
574 : rOutDev.ImplLogicYToDevicePixel(rSrcPt.Y()),
575 : rOutDev.ImplLogicWidthToDevicePixel(rSrcSize.Width()),
576 : rOutDev.ImplLogicHeightToDevicePixel(rSrcSize.Height()),
577 : ImplLogicXToDevicePixel(rDestPt.X()),
578 : ImplLogicYToDevicePixel(rDestPt.Y()),
579 : ImplLogicWidthToDevicePixel(rDestSize.Width()),
580 93076 : ImplLogicHeightToDevicePixel(rDestSize.Height()));
581 :
582 93076 : if( mpAlphaVDev )
583 : {
584 0 : if( rOutDev.mpAlphaVDev )
585 : {
586 : // alpha-blend source over destination
587 0 : DrawBitmapEx( rDestPt, rDestSize, rOutDev.GetBitmapEx(rSrcPt, rSrcSize) );
588 : }
589 : else
590 : {
591 0 : drawOutDevDirect( &rOutDev, aPosAry );
592 :
593 : // #i32109#: make destination rectangle opaque - source has no alpha
594 0 : mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, rDestSize) );
595 : }
596 : }
597 : else
598 : {
599 93076 : if( rOutDev.mpAlphaVDev )
600 : {
601 : // alpha-blend source over destination
602 0 : DrawBitmapEx( rDestPt, rDestSize, rOutDev.GetBitmapEx(rSrcPt, rSrcSize) );
603 : }
604 : else
605 : {
606 : // no alpha at all, neither in source nor destination device
607 93076 : drawOutDevDirect( &rOutDev, aPosAry );
608 : }
609 : }
610 : }
611 :
612 0 : void OutputDevice::CopyArea( const Point& rDestPt,
613 : const Point& rSrcPt, const Size& rSrcSize,
614 : bool bWindowInvalidate )
615 : {
616 0 : if ( ImplIsRecordLayout() )
617 0 : return;
618 :
619 0 : RasterOp eOldRop = GetRasterOp();
620 0 : SetRasterOp( ROP_OVERPAINT );
621 :
622 0 : if ( !IsDeviceOutputNecessary() )
623 0 : return;
624 :
625 0 : if ( !mpGraphics )
626 0 : if ( !AcquireGraphics() )
627 0 : return;
628 :
629 0 : if ( mbInitClipRegion )
630 0 : InitClipRegion();
631 :
632 0 : if ( mbOutputClipped )
633 0 : return;
634 :
635 0 : long nSrcWidth = ImplLogicWidthToDevicePixel( rSrcSize.Width() );
636 0 : long nSrcHeight = ImplLogicHeightToDevicePixel( rSrcSize.Height() );
637 0 : if (nSrcWidth && nSrcHeight)
638 : {
639 : SalTwoRect aPosAry(ImplLogicXToDevicePixel(rSrcPt.X()), ImplLogicYToDevicePixel(rSrcPt.Y()),
640 : nSrcWidth, nSrcHeight,
641 : ImplLogicXToDevicePixel(rDestPt.X()), ImplLogicYToDevicePixel(rDestPt.Y()),
642 0 : nSrcWidth, nSrcHeight);
643 :
644 : const Rectangle aSrcOutRect( Point( mnOutOffX, mnOutOffY ),
645 0 : Size( mnOutWidth, mnOutHeight ) );
646 :
647 0 : AdjustTwoRect( aPosAry, aSrcOutRect );
648 :
649 0 : CopyDeviceArea( aPosAry, bWindowInvalidate );
650 : }
651 :
652 0 : SetRasterOp( eOldRop );
653 :
654 0 : if( mpAlphaVDev )
655 0 : mpAlphaVDev->CopyArea( rDestPt, rSrcPt, rSrcSize, bWindowInvalidate );
656 : }
657 :
658 : // Direct OutputDevice drawing protected function
659 :
660 0 : void OutputDevice::CopyDeviceArea( SalTwoRect& aPosAry, bool /*bWindowInvalidate*/)
661 : {
662 0 : if (aPosAry.mnSrcWidth == 0 || aPosAry.mnSrcHeight == 0 || aPosAry.mnDestWidth == 0 || aPosAry.mnDestHeight == 0)
663 0 : return;
664 :
665 0 : aPosAry.mnDestWidth = aPosAry.mnSrcWidth;
666 0 : aPosAry.mnDestHeight = aPosAry.mnSrcHeight;
667 0 : mpGraphics->CopyBits(aPosAry, NULL, this, NULL);
668 : }
669 :
670 : // Direct OutputDevice drawing private function
671 :
672 93076 : void OutputDevice::drawOutDevDirect( const OutputDevice* pSrcDev, SalTwoRect& rPosAry )
673 : {
674 : SalGraphics* pSrcGraphics;
675 :
676 93076 : if ( this == pSrcDev )
677 0 : pSrcGraphics = NULL;
678 : else
679 : {
680 115217 : if ( (GetOutDevType() != pSrcDev->GetOutDevType()) ||
681 22141 : (GetOutDevType() != OUTDEV_WINDOW) )
682 : {
683 93076 : if ( !pSrcDev->mpGraphics )
684 : {
685 0 : if ( !pSrcDev->AcquireGraphics() )
686 0 : return;
687 : }
688 93076 : pSrcGraphics = pSrcDev->mpGraphics;
689 : }
690 : else
691 : {
692 0 : if ( static_cast<vcl::Window*>(this)->mpWindowImpl->mpFrameWindow == static_cast<const vcl::Window*>(pSrcDev)->mpWindowImpl->mpFrameWindow )
693 0 : pSrcGraphics = NULL;
694 : else
695 : {
696 0 : if ( !pSrcDev->mpGraphics )
697 : {
698 0 : if ( !pSrcDev->AcquireGraphics() )
699 0 : return;
700 : }
701 0 : pSrcGraphics = pSrcDev->mpGraphics;
702 :
703 0 : if ( !mpGraphics )
704 : {
705 0 : if ( !AcquireGraphics() )
706 0 : return;
707 : }
708 : DBG_ASSERT( mpGraphics && pSrcDev->mpGraphics,
709 : "OutputDevice::DrawOutDev(): We need more than one Graphics" );
710 : }
711 : }
712 : }
713 :
714 : // #102532# Offset only has to be pseudo window offset
715 : const Rectangle aSrcOutRect( Point( pSrcDev->mnOutOffX, pSrcDev->mnOutOffY ),
716 93076 : Size( pSrcDev->mnOutWidth, pSrcDev->mnOutHeight ) );
717 :
718 93076 : AdjustTwoRect( rPosAry, aSrcOutRect );
719 :
720 93076 : if ( rPosAry.mnSrcWidth && rPosAry.mnSrcHeight && rPosAry.mnDestWidth && rPosAry.mnDestHeight )
721 : {
722 : // --- RTL --- if this is no window, but pSrcDev is a window
723 : // mirroring may be required
724 : // because only windows have a SalGraphicsLayout
725 : // mirroring is performed here
726 92978 : if( (GetOutDevType() != OUTDEV_WINDOW) && pSrcGraphics && (pSrcGraphics->GetLayout() & SalLayoutFlags::BiDiRtl) )
727 : {
728 0 : SalTwoRect aPosAry2 = rPosAry;
729 0 : pSrcGraphics->mirror( aPosAry2.mnSrcX, aPosAry2.mnSrcWidth, pSrcDev );
730 0 : mpGraphics->CopyBits( aPosAry2, pSrcGraphics, this, pSrcDev );
731 : }
732 : else
733 92978 : mpGraphics->CopyBits( rPosAry, pSrcGraphics, this, pSrcDev );
734 : }
735 : }
736 :
737 : // Layout public functions
738 :
739 114119 : void OutputDevice::EnableRTL( bool bEnable )
740 : {
741 114119 : mbEnableRTL = bEnable;
742 :
743 114119 : if( mpAlphaVDev )
744 12799 : mpAlphaVDev->EnableRTL( bEnable );
745 114119 : }
746 :
747 875100 : bool OutputDevice::ImplIsAntiparallel() const
748 : {
749 875100 : bool bRet = false;
750 875100 : if( AcquireGraphics() )
751 : {
752 3503551 : if( ( (mpGraphics->GetLayout() & SalLayoutFlags::BiDiRtl) && ! IsRTLEnabled() ) ||
753 3473490 : ( ! (mpGraphics->GetLayout() & SalLayoutFlags::BiDiRtl) && IsRTLEnabled() ) )
754 : {
755 3151 : bRet = true;
756 : }
757 : }
758 875100 : return bRet;
759 : }
760 :
761 : // note: the coordinates to be remirrored are in frame coordiantes !
762 :
763 42 : void OutputDevice::ReMirror( Point &rPoint ) const
764 : {
765 42 : rPoint.X() = mnOutOffX + mnOutWidth - 1 - rPoint.X() + mnOutOffX;
766 42 : }
767 90 : void OutputDevice::ReMirror( Rectangle &rRect ) const
768 : {
769 90 : long nWidth = rRect.Right() - rRect.Left();
770 :
771 : //long lc_x = rRect.nLeft - mnOutOffX; // normalize
772 : //lc_x = mnOutWidth - nWidth - 1 - lc_x; // mirror
773 : //rRect.nLeft = lc_x + mnOutOffX; // re-normalize
774 :
775 90 : rRect.Left() = mnOutOffX + mnOutWidth - nWidth - 1 - rRect.Left() + mnOutOffX;
776 90 : rRect.Right() = rRect.Left() + nWidth;
777 90 : }
778 :
779 1450 : void OutputDevice::ReMirror( vcl::Region &rRegion ) const
780 : {
781 1450 : RectangleVector aRectangles;
782 1450 : rRegion.GetRegionRectangles(aRectangles);
783 2900 : vcl::Region aMirroredRegion;
784 :
785 1495 : for(RectangleVector::iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); ++aRectIter)
786 : {
787 45 : ReMirror(*aRectIter);
788 45 : aMirroredRegion.Union(*aRectIter);
789 : }
790 :
791 2900 : rRegion = aMirroredRegion;
792 :
793 1450 : }
794 :
795 997479 : bool OutputDevice::HasMirroredGraphics() const
796 : {
797 997479 : return ( AcquireGraphics() && (mpGraphics->GetLayout() & SalLayoutFlags::BiDiRtl) );
798 : }
799 :
800 5183766 : bool OutputDevice::ImplIsRecordLayout() const
801 : {
802 5183766 : return mpOutDevData->mpRecordLayout;
803 : }
804 :
805 : // EPS public function
806 :
807 0 : bool OutputDevice::DrawEPS( const Point& rPoint, const Size& rSize,
808 : const GfxLink& rGfxLink, GDIMetaFile* pSubst )
809 : {
810 0 : bool bDrawn(true);
811 :
812 0 : if ( mpMetaFile )
813 : {
814 0 : GDIMetaFile aSubst;
815 :
816 0 : if( pSubst )
817 0 : aSubst = *pSubst;
818 :
819 0 : mpMetaFile->AddAction( new MetaEPSAction( rPoint, rSize, rGfxLink, aSubst ) );
820 : }
821 :
822 0 : if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
823 0 : return bDrawn;
824 :
825 0 : if( mbOutputClipped )
826 0 : return bDrawn;
827 :
828 0 : Rectangle aRect( ImplLogicToDevicePixel( Rectangle( rPoint, rSize ) ) );
829 :
830 0 : if( !aRect.IsEmpty() )
831 : {
832 : // draw the real EPS graphics
833 0 : if( rGfxLink.GetData() && rGfxLink.GetDataSize() )
834 : {
835 0 : if( !mpGraphics && !AcquireGraphics() )
836 0 : return bDrawn;
837 :
838 0 : if( mbInitClipRegion )
839 0 : InitClipRegion();
840 :
841 0 : aRect.Justify();
842 0 : bDrawn = mpGraphics->DrawEPS( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(),
843 0 : const_cast<sal_uInt8*>(rGfxLink.GetData()), rGfxLink.GetDataSize(), this );
844 : }
845 :
846 : // else draw the substitution graphics
847 0 : if( !bDrawn && pSubst )
848 : {
849 0 : GDIMetaFile* pOldMetaFile = mpMetaFile;
850 :
851 0 : mpMetaFile = NULL;
852 0 : Graphic( *pSubst ).Draw( this, rPoint, rSize );
853 0 : mpMetaFile = pOldMetaFile;
854 : }
855 : }
856 :
857 0 : if( mpAlphaVDev )
858 0 : mpAlphaVDev->DrawEPS( rPoint, rSize, rGfxLink, pSubst );
859 :
860 0 : return bDrawn;
861 : }
862 :
863 162136 : void OutputDevice::BeginPaint()
864 : {
865 162136 : if( mpGraphics || AcquireGraphics() )
866 162136 : mpGraphics->BeginPaint();
867 162136 : }
868 :
869 162136 : void OutputDevice::EndPaint()
870 : {
871 162136 : if( mpGraphics || AcquireGraphics() )
872 162136 : mpGraphics->EndPaint();
873 162937 : }
874 :
875 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|