Coverage Report

Created: 2025-07-07 10:01

/src/libreoffice/vcl/source/window/clipping.cxx
Line
Count
Source (jump to first uncovered line)
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/window.hxx>
21
#include <vcl/virdev.hxx>
22
23
#include <tools/debug.hxx>
24
25
#include <salobj.hxx>
26
#include <window.h>
27
28
namespace vcl {
29
30
vcl::Region WindowOutputDevice::GetOutputBoundsClipRegion() const
31
0
{
32
0
    vcl::Region aClip(GetClipRegion());
33
0
    aClip.Intersect(tools::Rectangle(Point(), GetOutputSize()));
34
35
0
    return aClip;
36
0
}
37
38
void WindowOutputDevice::InitClipRegion()
39
0
{
40
0
    DBG_TESTSOLARMUTEX();
41
42
0
    vcl::Region  aRegion;
43
44
0
    if ( mxOwnerWindow->mpWindowImpl->mbInPaint )
45
0
        aRegion = *(mxOwnerWindow->mpWindowImpl->mpPaintRegion);
46
0
    else
47
0
    {
48
0
        aRegion = mxOwnerWindow->ImplGetWinChildClipRegion();
49
        // only this region is in frame coordinates, so re-mirror it
50
        // the mpWindowImpl->mpPaintRegion above is already correct (see ImplCallPaint()) !
51
0
        if( ImplIsAntiparallel() )
52
0
            ReMirror ( aRegion );
53
0
    }
54
0
    if ( mbClipRegion )
55
0
        aRegion.Intersect( ImplPixelToDevicePixel( maRegion ) );
56
0
    if ( aRegion.IsEmpty() )
57
0
        mbOutputClipped = true;
58
0
    else
59
0
    {
60
0
        mbOutputClipped = false;
61
0
        SelectClipRegion( aRegion );
62
0
    }
63
0
    mbClipRegionSet = true;
64
65
0
    mbInitClipRegion = false;
66
0
}
67
68
void Window::SetParentClipMode( ParentClipMode nMode )
69
0
{
70
0
    if ( mpWindowImpl->mpBorderWindow )
71
0
        mpWindowImpl->mpBorderWindow->SetParentClipMode( nMode );
72
0
    else
73
0
    {
74
0
        if ( !ImplIsOverlapWindow() )
75
0
        {
76
0
            mpWindowImpl->mnParentClipMode = nMode;
77
0
            if ( nMode & ParentClipMode::Clip )
78
0
                mpWindowImpl->mpParent->mpWindowImpl->mbClipChildren = true;
79
0
        }
80
0
    }
81
0
}
82
83
ParentClipMode Window::GetParentClipMode() const
84
0
{
85
0
    if ( mpWindowImpl->mpBorderWindow )
86
0
        return mpWindowImpl->mpBorderWindow->GetParentClipMode();
87
0
    else
88
0
        return mpWindowImpl->mnParentClipMode;
89
0
}
90
91
void Window::ExpandPaintClipRegion( const vcl::Region& rRegion )
92
0
{
93
0
    if( !mpWindowImpl->mpPaintRegion )
94
0
        return;
95
96
0
    vcl::Region aPixRegion = LogicToPixel( rRegion );
97
0
    vcl::Region aDevPixRegion = GetOutDev()->ImplPixelToDevicePixel( aPixRegion );
98
99
0
    vcl::Region aWinChildRegion = ImplGetWinChildClipRegion();
100
    // only this region is in frame coordinates, so re-mirror it
101
0
    if( GetOutDev()->ImplIsAntiparallel() )
102
0
    {
103
0
        const OutputDevice *pOutDev = GetOutDev();
104
0
        pOutDev->ReMirror( aWinChildRegion );
105
0
    }
106
107
0
    aDevPixRegion.Intersect( aWinChildRegion );
108
0
    if( ! aDevPixRegion.IsEmpty() )
109
0
    {
110
0
        mpWindowImpl->mpPaintRegion->Union( aDevPixRegion );
111
0
        GetOutDev()->mbInitClipRegion = true;
112
0
    }
113
0
}
114
115
vcl::Region Window::GetWindowClipRegionPixel() const
116
0
{
117
0
    vcl::Region aWinClipRegion;
118
119
0
    if ( mpWindowImpl->mbInitWinClipRegion )
120
0
        const_cast<vcl::Window*>(this)->ImplInitWinClipRegion();
121
0
    aWinClipRegion = mpWindowImpl->maWinClipRegion;
122
123
0
    vcl::Region   aWinRegion( GetOutputRectPixel() );
124
125
0
    if ( aWinRegion == aWinClipRegion )
126
0
        aWinClipRegion.SetNull();
127
128
0
    aWinClipRegion.Move( -GetOutDev()->mnOutOffX, -GetOutDev()->mnOutOffY );
129
130
0
    return aWinClipRegion;
131
0
}
132
133
134
vcl::Region WindowOutputDevice::GetActiveClipRegion() const
135
0
{
136
0
    vcl::Region aRegion(true);
137
138
0
    if ( mxOwnerWindow->mpWindowImpl->mbInPaint )
139
0
    {
140
0
        aRegion = *(mxOwnerWindow->mpWindowImpl->mpPaintRegion);
141
0
        aRegion.Move( -mnOutOffX, -mnOutOffY );
142
0
    }
143
144
0
    if ( mbClipRegion )
145
0
        aRegion.Intersect( maRegion );
146
147
0
    return PixelToLogic( aRegion );
148
0
}
149
150
void WindowOutputDevice::ClipToPaintRegion(tools::Rectangle& rDstRect)
151
0
{
152
0
    const vcl::Region aPaintRgn(mxOwnerWindow->GetPaintRegion());
153
154
0
    if (!aPaintRgn.IsNull())
155
0
        rDstRect.Intersection(LogicToPixel(aPaintRgn.GetBoundRect()));
156
0
}
157
158
void Window::EnableClipSiblings( bool bClipSiblings )
159
0
{
160
161
0
    if ( mpWindowImpl->mpBorderWindow )
162
0
        mpWindowImpl->mpBorderWindow->EnableClipSiblings( bClipSiblings );
163
164
0
    mpWindowImpl->mbClipSiblings = bClipSiblings;
165
0
}
166
167
void Window::ImplClipBoundaries( vcl::Region& rRegion, bool bThis, bool bOverlaps )
168
0
{
169
0
    if ( bThis )
170
0
        ImplIntersectWindowClipRegion( rRegion );
171
0
    else if ( ImplIsOverlapWindow() )
172
0
    {
173
        // clip to frame if required
174
0
        if ( !mpWindowImpl->mbFrame )
175
0
            rRegion.Intersect( tools::Rectangle( Point( 0, 0 ), mpWindowImpl->mpFrameWindow->GetOutputSizePixel() ) );
176
177
0
        if ( bOverlaps && !rRegion.IsEmpty() )
178
0
        {
179
            // Clip Overlap Siblings
180
0
            vcl::Window* pStartOverlapWindow = this;
181
0
            while ( !pStartOverlapWindow->mpWindowImpl->mbFrame )
182
0
            {
183
0
                vcl::Window* pOverlapWindow = pStartOverlapWindow->mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap;
184
0
                while ( pOverlapWindow && (pOverlapWindow != pStartOverlapWindow) )
185
0
                {
186
0
                    pOverlapWindow->ImplExcludeOverlapWindows2( rRegion );
187
0
                    pOverlapWindow = pOverlapWindow->mpWindowImpl->mpNext;
188
0
                }
189
0
                pStartOverlapWindow = pStartOverlapWindow->mpWindowImpl->mpOverlapWindow;
190
0
            }
191
192
            // Clip Child Overlap Windows
193
0
            ImplExcludeOverlapWindows( rRegion );
194
0
        }
195
0
    }
196
0
    else
197
0
        ImplGetParent()->ImplIntersectWindowClipRegion( rRegion );
198
0
}
199
200
bool Window::ImplClipChildren( vcl::Region& rRegion ) const
201
0
{
202
0
    bool    bOtherClip = false;
203
0
    vcl::Window* pWindow = mpWindowImpl->mpFirstChild;
204
0
    while ( pWindow )
205
0
    {
206
0
        if ( pWindow->mpWindowImpl->mbReallyVisible )
207
0
        {
208
            // read-out ParentClipMode-Flags
209
0
            ParentClipMode nClipMode = pWindow->GetParentClipMode();
210
0
            if ( !(nClipMode & ParentClipMode::NoClip) &&
211
0
                 ((nClipMode & ParentClipMode::Clip) || (GetStyle() & WB_CLIPCHILDREN)) )
212
0
                pWindow->ImplExcludeWindowRegion( rRegion );
213
0
            else
214
0
                bOtherClip = true;
215
0
        }
216
217
0
        pWindow = pWindow->mpWindowImpl->mpNext;
218
0
    }
219
220
0
    return bOtherClip;
221
0
}
222
223
void Window::ImplClipAllChildren( vcl::Region& rRegion ) const
224
0
{
225
0
    vcl::Window* pWindow = mpWindowImpl->mpFirstChild;
226
0
    while ( pWindow )
227
0
    {
228
0
        if ( pWindow->mpWindowImpl->mbReallyVisible )
229
0
            pWindow->ImplExcludeWindowRegion( rRegion );
230
0
        pWindow = pWindow->mpWindowImpl->mpNext;
231
0
    }
232
0
}
233
234
void Window::ImplClipSiblings( vcl::Region& rRegion ) const
235
0
{
236
0
    vcl::Window* pWindow = ImplGetParent()->mpWindowImpl->mpFirstChild;
237
0
    while ( pWindow )
238
0
    {
239
0
        if ( pWindow == this )
240
0
            break;
241
242
0
        if ( pWindow->mpWindowImpl->mbReallyVisible )
243
0
            pWindow->ImplExcludeWindowRegion( rRegion );
244
245
0
        pWindow = pWindow->mpWindowImpl->mpNext;
246
0
    }
247
0
}
248
249
void Window::ImplInitWinClipRegion()
250
0
{
251
    // Build Window Region
252
0
    mpWindowImpl->maWinClipRegion = GetOutputRectPixel();
253
0
    if ( mpWindowImpl->mbWinRegion )
254
0
        mpWindowImpl->maWinClipRegion.Intersect( GetOutDev()->ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
255
256
    // ClipSiblings
257
0
    if ( mpWindowImpl->mbClipSiblings && !ImplIsOverlapWindow() )
258
0
        ImplClipSiblings( mpWindowImpl->maWinClipRegion );
259
260
    // Clip Parent Boundaries
261
0
    ImplClipBoundaries( mpWindowImpl->maWinClipRegion, false, true );
262
263
    // Clip Children
264
0
    if ( (GetStyle() & WB_CLIPCHILDREN) || mpWindowImpl->mbClipChildren )
265
0
        mpWindowImpl->mbInitChildRegion = true;
266
267
0
    mpWindowImpl->mbInitWinClipRegion = false;
268
0
}
269
270
void Window::ImplInitWinChildClipRegion()
271
0
{
272
0
    if ( !mpWindowImpl->mpFirstChild )
273
0
    {
274
0
        mpWindowImpl->mpChildClipRegion.reset();
275
0
    }
276
0
    else
277
0
    {
278
0
        if ( !mpWindowImpl->mpChildClipRegion )
279
0
            mpWindowImpl->mpChildClipRegion.reset( new vcl::Region( mpWindowImpl->maWinClipRegion ) );
280
0
        else
281
0
            *mpWindowImpl->mpChildClipRegion = mpWindowImpl->maWinClipRegion;
282
283
0
        ImplClipChildren( *mpWindowImpl->mpChildClipRegion );
284
0
    }
285
286
0
    mpWindowImpl->mbInitChildRegion = false;
287
0
}
288
289
Region& Window::ImplGetWinChildClipRegion()
290
0
{
291
0
    if ( mpWindowImpl->mbInitWinClipRegion )
292
0
        ImplInitWinClipRegion();
293
0
    if ( mpWindowImpl->mbInitChildRegion )
294
0
        ImplInitWinChildClipRegion();
295
0
    if ( mpWindowImpl->mpChildClipRegion )
296
0
        return *mpWindowImpl->mpChildClipRegion;
297
0
    return mpWindowImpl->maWinClipRegion;
298
0
}
299
300
bool Window::ImplSysObjClip( const vcl::Region* pOldRegion )
301
0
{
302
0
    bool bUpdate = true;
303
304
0
    if ( mpWindowImpl->mpSysObj )
305
0
    {
306
0
        bool bVisibleState = mpWindowImpl->mbReallyVisible;
307
308
0
        if ( bVisibleState )
309
0
        {
310
0
            vcl::Region& rWinChildClipRegion = ImplGetWinChildClipRegion();
311
312
0
            if (!rWinChildClipRegion.IsEmpty())
313
0
            {
314
0
                if ( pOldRegion )
315
0
                {
316
0
                    vcl::Region aNewRegion = rWinChildClipRegion;
317
0
                    rWinChildClipRegion.Intersect(*pOldRegion);
318
0
                    bUpdate = aNewRegion == rWinChildClipRegion;
319
0
                }
320
321
0
                vcl::Region      aRegion = rWinChildClipRegion;
322
0
                vcl::Region      aWinRectRegion( GetOutputRectPixel() );
323
324
0
                if ( aRegion == aWinRectRegion )
325
0
                    mpWindowImpl->mpSysObj->ResetClipRegion();
326
0
                else
327
0
                {
328
0
                    aRegion.Move( -GetOutDev()->mnOutOffX, -GetOutDev()->mnOutOffY );
329
330
                    // set/update clip region
331
0
                    RectangleVector aRectangles;
332
0
                    aRegion.GetRegionRectangles(aRectangles);
333
0
                    mpWindowImpl->mpSysObj->BeginSetClipRegion(aRectangles.size());
334
335
0
                    for (auto const& rectangle : aRectangles)
336
0
                    {
337
0
                        mpWindowImpl->mpSysObj->UnionClipRegion(
338
0
                            rectangle.Left(),
339
0
                            rectangle.Top(),
340
0
                            rectangle.GetWidth(),   // orig nWidth was ((R - L) + 1), same as GetWidth does
341
0
                            rectangle.GetHeight()); // same for height
342
0
                    }
343
344
0
                    mpWindowImpl->mpSysObj->EndSetClipRegion();
345
0
                }
346
0
            }
347
0
            else
348
0
                bVisibleState = false;
349
0
        }
350
351
        // update visible status
352
0
        mpWindowImpl->mpSysObj->Show( bVisibleState );
353
0
    }
354
355
0
    return bUpdate;
356
0
}
357
358
void Window::ImplUpdateSysObjChildrenClip()
359
0
{
360
0
    if ( mpWindowImpl->mpSysObj && mpWindowImpl->mbInitWinClipRegion )
361
0
        ImplSysObjClip( nullptr );
362
363
0
    vcl::Window* pWindow = mpWindowImpl->mpFirstChild;
364
0
    while ( pWindow )
365
0
    {
366
0
        pWindow->ImplUpdateSysObjChildrenClip();
367
0
        pWindow = pWindow->mpWindowImpl->mpNext;
368
0
    }
369
0
}
370
371
void Window::ImplUpdateSysObjOverlapsClip()
372
0
{
373
0
    ImplUpdateSysObjChildrenClip();
374
375
0
    vcl::Window* pWindow = mpWindowImpl->mpFirstOverlap;
376
0
    while ( pWindow )
377
0
    {
378
0
        pWindow->ImplUpdateSysObjOverlapsClip();
379
0
        pWindow = pWindow->mpWindowImpl->mpNext;
380
0
    }
381
0
}
382
383
void Window::ImplUpdateSysObjClip()
384
0
{
385
0
    if ( !ImplIsOverlapWindow() )
386
0
    {
387
0
        ImplUpdateSysObjChildrenClip();
388
389
        // siblings should recalculate their clip region
390
0
        if ( mpWindowImpl->mbClipSiblings )
391
0
        {
392
0
            vcl::Window* pWindow = mpWindowImpl->mpNext;
393
0
            while ( pWindow )
394
0
            {
395
0
                pWindow->ImplUpdateSysObjChildrenClip();
396
0
                pWindow = pWindow->mpWindowImpl->mpNext;
397
0
            }
398
0
        }
399
0
    }
400
0
    else
401
0
        mpWindowImpl->mpFrameWindow->ImplUpdateSysObjOverlapsClip();
402
0
}
403
404
bool Window::ImplSetClipFlagChildren( bool bSysObjOnlySmaller )
405
0
{
406
0
    bool bUpdate = true;
407
0
    if ( mpWindowImpl->mpSysObj )
408
0
    {
409
0
        std::unique_ptr<vcl::Region> pOldRegion;
410
0
        if ( bSysObjOnlySmaller && !mpWindowImpl->mbInitWinClipRegion )
411
0
            pOldRegion.reset(new vcl::Region( mpWindowImpl->maWinClipRegion ));
412
413
0
        GetOutDev()->mbInitClipRegion = true;
414
0
        mpWindowImpl->mbInitWinClipRegion = true;
415
416
0
        vcl::Window* pWindow = mpWindowImpl->mpFirstChild;
417
0
        while ( pWindow )
418
0
        {
419
0
            if ( !pWindow->ImplSetClipFlagChildren( bSysObjOnlySmaller ) )
420
0
                bUpdate = false;
421
0
            pWindow = pWindow->mpWindowImpl->mpNext;
422
0
        }
423
424
0
        if ( !ImplSysObjClip( pOldRegion.get() ) )
425
0
        {
426
0
            GetOutDev()->mbInitClipRegion = true;
427
0
            mpWindowImpl->mbInitWinClipRegion = true;
428
0
            bUpdate = false;
429
0
        }
430
0
    }
431
0
    else
432
0
    {
433
0
        GetOutDev()->mbInitClipRegion = true;
434
0
        mpWindowImpl->mbInitWinClipRegion = true;
435
436
0
        vcl::Window* pWindow = mpWindowImpl->mpFirstChild;
437
0
        while ( pWindow )
438
0
        {
439
0
            if ( !pWindow->ImplSetClipFlagChildren( bSysObjOnlySmaller ) )
440
0
                bUpdate = false;
441
0
            pWindow = pWindow->mpWindowImpl->mpNext;
442
0
        }
443
0
    }
444
0
    return bUpdate;
445
0
}
446
447
bool Window::ImplSetClipFlagOverlapWindows( bool bSysObjOnlySmaller )
448
0
{
449
0
    bool bUpdate = ImplSetClipFlagChildren( bSysObjOnlySmaller );
450
451
0
    vcl::Window* pWindow = mpWindowImpl->mpFirstOverlap;
452
0
    while ( pWindow )
453
0
    {
454
0
        if ( !pWindow->ImplSetClipFlagOverlapWindows( bSysObjOnlySmaller ) )
455
0
            bUpdate = false;
456
0
        pWindow = pWindow->mpWindowImpl->mpNext;
457
0
    }
458
459
0
    return bUpdate;
460
0
}
461
462
bool Window::ImplSetClipFlag( bool bSysObjOnlySmaller )
463
0
{
464
0
    if ( !ImplIsOverlapWindow() )
465
0
    {
466
0
        bool bUpdate = ImplSetClipFlagChildren( bSysObjOnlySmaller );
467
468
0
        vcl::Window* pParent = ImplGetParent();
469
0
        if ( pParent &&
470
0
             ((pParent->GetStyle() & WB_CLIPCHILDREN) || (mpWindowImpl->mnParentClipMode & ParentClipMode::Clip)) )
471
0
        {
472
0
            pParent->GetOutDev()->mbInitClipRegion = true;
473
0
            pParent->mpWindowImpl->mbInitChildRegion = true;
474
0
        }
475
476
        // siblings should recalculate their clip region
477
0
        if ( mpWindowImpl->mbClipSiblings )
478
0
        {
479
0
            vcl::Window* pWindow = mpWindowImpl->mpNext;
480
0
            while ( pWindow )
481
0
            {
482
0
                if ( !pWindow->ImplSetClipFlagChildren( bSysObjOnlySmaller ) )
483
0
                    bUpdate = false;
484
0
                pWindow = pWindow->mpWindowImpl->mpNext;
485
0
            }
486
0
        }
487
488
0
        return bUpdate;
489
0
    }
490
0
    else
491
0
        return mpWindowImpl->mpFrameWindow->ImplSetClipFlagOverlapWindows( bSysObjOnlySmaller );
492
0
}
493
494
void Window::ImplIntersectWindowClipRegion( vcl::Region& rRegion )
495
0
{
496
0
    if ( mpWindowImpl->mbInitWinClipRegion )
497
0
        ImplInitWinClipRegion();
498
499
0
    rRegion.Intersect( mpWindowImpl->maWinClipRegion );
500
0
}
501
502
void Window::ImplIntersectWindowRegion( vcl::Region& rRegion )
503
0
{
504
0
    rRegion.Intersect( GetOutputRectPixel() );
505
0
    if ( mpWindowImpl->mbWinRegion )
506
0
        rRegion.Intersect( GetOutDev()->ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
507
0
}
508
509
void Window::ImplExcludeWindowRegion( vcl::Region& rRegion )
510
0
{
511
0
    if ( mpWindowImpl->mbWinRegion )
512
0
    {
513
0
        vcl::Region aRegion( GetOutputRectPixel() );
514
0
        aRegion.Intersect( GetOutDev()->ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
515
0
        rRegion.Exclude( aRegion );
516
0
    }
517
0
    else
518
0
    {
519
0
        rRegion.Exclude( GetOutputRectPixel() );
520
0
    }
521
0
}
522
523
void Window::ImplExcludeOverlapWindows( vcl::Region& rRegion ) const
524
0
{
525
0
    vcl::Window* pWindow = mpWindowImpl->mpFirstOverlap;
526
0
    while ( pWindow )
527
0
    {
528
0
        if ( pWindow->mpWindowImpl->mbReallyVisible )
529
0
        {
530
0
            pWindow->ImplExcludeWindowRegion( rRegion );
531
0
            pWindow->ImplExcludeOverlapWindows( rRegion );
532
0
        }
533
534
0
        pWindow = pWindow->mpWindowImpl->mpNext;
535
0
    }
536
0
}
537
538
void Window::ImplExcludeOverlapWindows2( vcl::Region& rRegion )
539
0
{
540
0
    if ( mpWindowImpl->mbReallyVisible )
541
0
        ImplExcludeWindowRegion( rRegion );
542
543
0
    ImplExcludeOverlapWindows( rRegion );
544
0
}
545
546
void Window::ImplIntersectAndUnionOverlapWindows( const vcl::Region& rInterRegion, vcl::Region& rRegion ) const
547
0
{
548
0
    vcl::Window* pWindow = mpWindowImpl->mpFirstOverlap;
549
0
    while ( pWindow )
550
0
    {
551
0
        if ( pWindow->mpWindowImpl->mbReallyVisible )
552
0
        {
553
0
            vcl::Region aTempRegion( rInterRegion );
554
0
            pWindow->ImplIntersectWindowRegion( aTempRegion );
555
0
            rRegion.Union( aTempRegion );
556
0
            pWindow->ImplIntersectAndUnionOverlapWindows( rInterRegion, rRegion );
557
0
        }
558
559
0
        pWindow = pWindow->mpWindowImpl->mpNext;
560
0
    }
561
0
}
562
563
void Window::ImplIntersectAndUnionOverlapWindows2( const vcl::Region& rInterRegion, vcl::Region& rRegion )
564
0
{
565
0
    if ( mpWindowImpl->mbReallyVisible )
566
0
    {
567
0
        vcl::Region aTempRegion( rInterRegion );
568
0
        ImplIntersectWindowRegion( aTempRegion );
569
0
        rRegion.Union( aTempRegion );
570
0
    }
571
572
0
    ImplIntersectAndUnionOverlapWindows( rInterRegion, rRegion );
573
0
}
574
575
void Window::ImplCalcOverlapRegionOverlaps( const vcl::Region& rInterRegion, vcl::Region& rRegion ) const
576
0
{
577
    // Clip Overlap Siblings
578
0
    vcl::Window const * pStartOverlapWindow;
579
0
    if ( !ImplIsOverlapWindow() )
580
0
        pStartOverlapWindow = mpWindowImpl->mpOverlapWindow;
581
0
    else
582
0
        pStartOverlapWindow = this;
583
0
    while ( !pStartOverlapWindow->mpWindowImpl->mbFrame )
584
0
    {
585
0
        vcl::Window* pOverlapWindow = pStartOverlapWindow->mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap;
586
0
        while ( pOverlapWindow && (pOverlapWindow != pStartOverlapWindow) )
587
0
        {
588
0
            pOverlapWindow->ImplIntersectAndUnionOverlapWindows2( rInterRegion, rRegion );
589
0
            pOverlapWindow = pOverlapWindow->mpWindowImpl->mpNext;
590
0
        }
591
0
        pStartOverlapWindow = pStartOverlapWindow->mpWindowImpl->mpOverlapWindow;
592
0
    }
593
594
    // Clip Child Overlap Windows
595
0
    if ( !ImplIsOverlapWindow() )
596
0
        mpWindowImpl->mpOverlapWindow->ImplIntersectAndUnionOverlapWindows( rInterRegion, rRegion );
597
0
    else
598
0
        ImplIntersectAndUnionOverlapWindows( rInterRegion, rRegion );
599
0
}
600
601
void Window::ImplCalcOverlapRegion( const tools::Rectangle& rSourceRect, vcl::Region& rRegion,
602
                                    bool bChildren, bool bSiblings )
603
0
{
604
0
    vcl::Region  aRegion( rSourceRect );
605
0
    if ( mpWindowImpl->mbWinRegion )
606
0
        rRegion.Intersect( GetOutDev()->ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
607
0
    vcl::Region  aTempRegion;
608
0
    vcl::Window* pWindow;
609
610
0
    ImplCalcOverlapRegionOverlaps( aRegion, rRegion );
611
612
    // Parent-Boundaries
613
0
    pWindow = this;
614
0
    if ( !ImplIsOverlapWindow() )
615
0
    {
616
0
        pWindow = ImplGetParent();
617
0
        do
618
0
        {
619
0
            aTempRegion = aRegion;
620
0
            pWindow->ImplExcludeWindowRegion( aTempRegion );
621
0
            rRegion.Union( aTempRegion );
622
0
            if ( pWindow->ImplIsOverlapWindow() )
623
0
                break;
624
0
            pWindow = pWindow->ImplGetParent();
625
0
        }
626
0
        while ( pWindow );
627
0
    }
628
0
    if ( pWindow && !pWindow->mpWindowImpl->mbFrame )
629
0
    {
630
0
        aTempRegion = aRegion;
631
0
        aTempRegion.Exclude( tools::Rectangle( Point( 0, 0 ), mpWindowImpl->mpFrameWindow->GetOutputSizePixel() ) );
632
0
        rRegion.Union( aTempRegion );
633
0
    }
634
635
    // Siblings
636
0
    if ( bSiblings && !ImplIsOverlapWindow() )
637
0
    {
638
0
        pWindow = mpWindowImpl->mpParent->mpWindowImpl->mpFirstChild;
639
0
        do
640
0
        {
641
0
            if ( pWindow->mpWindowImpl->mbReallyVisible && (pWindow != this) )
642
0
            {
643
0
                aTempRegion = aRegion;
644
0
                pWindow->ImplIntersectWindowRegion( aTempRegion );
645
0
                rRegion.Union( aTempRegion );
646
0
            }
647
0
            pWindow = pWindow->mpWindowImpl->mpNext;
648
0
        }
649
0
        while ( pWindow );
650
0
    }
651
652
0
    if ( !bChildren )
653
0
        return;
654
655
0
    pWindow = mpWindowImpl->mpFirstChild;
656
0
    while ( pWindow )
657
0
    {
658
0
        if ( pWindow->mpWindowImpl->mbReallyVisible )
659
0
        {
660
0
            aTempRegion = aRegion;
661
0
            pWindow->ImplIntersectWindowRegion( aTempRegion );
662
0
            rRegion.Union( aTempRegion );
663
0
        }
664
0
        pWindow = pWindow->mpWindowImpl->mpNext;
665
0
    }
666
0
}
667
668
void WindowOutputDevice::SaveBackground(VirtualDevice& rSaveDevice, const Point& rPos, const Size& rSize, const Size&) const
669
0
{
670
0
    MapMode aTempMap(GetMapMode());
671
0
    aTempMap.SetOrigin(Point());
672
0
    rSaveDevice.SetMapMode(aTempMap);
673
674
0
    if ( mxOwnerWindow->mpWindowImpl->mpPaintRegion )
675
0
    {
676
0
        vcl::Region      aClip( *mxOwnerWindow->mpWindowImpl->mpPaintRegion );
677
0
        const Point aPixPos( LogicToPixel( rPos ) );
678
679
0
        aClip.Move( -mnOutOffX, -mnOutOffY );
680
0
        aClip.Intersect( tools::Rectangle( aPixPos, LogicToPixel( rSize ) ) );
681
682
0
        if ( !aClip.IsEmpty() )
683
0
        {
684
0
            const vcl::Region    aOldClip( rSaveDevice.GetClipRegion() );
685
0
            const Point     aPixOffset( rSaveDevice.LogicToPixel( Point() ) );
686
0
            const bool      bMap = rSaveDevice.IsMapModeEnabled();
687
688
            // move clip region to have the same distance to DestOffset
689
0
            aClip.Move( aPixOffset.X() - aPixPos.X(), aPixOffset.Y() - aPixPos.Y() );
690
691
            // set pixel clip region
692
0
            rSaveDevice.EnableMapMode( false );
693
0
            rSaveDevice.SetClipRegion( aClip );
694
0
            rSaveDevice.EnableMapMode( bMap );
695
0
            rSaveDevice.DrawOutDev( Point(), rSize, rPos, rSize, *this );
696
0
            rSaveDevice.SetClipRegion( aOldClip );
697
0
        }
698
0
    }
699
0
    else
700
0
    {
701
0
        rSaveDevice.DrawOutDev( Point(), rSize, rPos, rSize, *this );
702
0
    }
703
704
0
    rSaveDevice.SetMapMode(MapMode());
705
0
}
706
707
} /* namespace vcl */
708
709
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */