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