Coverage Report

Created: 2025-12-08 09:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/vcl/source/outdev/outdev.cxx
Line
Count
Source
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 <sal/config.h>
21
22
#include <sal/log.hxx>
23
#include <comphelper/processfactory.hxx>
24
#include <tools/debug.hxx>
25
26
#include <vcl/graph.hxx>
27
#include <tools/lazydelete.hxx>
28
#include <vcl/metaact.hxx>
29
#include <vcl/toolkit/unowrap.hxx>
30
#include <vcl/svapp.hxx>
31
#include <vcl/sysdata.hxx>
32
#include <vcl/virdev.hxx>
33
34
#include <ImplOutDevData.hxx>
35
#include <font/PhysicalFontFaceCollection.hxx>
36
#include <salgdi.hxx>
37
#include <window.h>
38
39
#include <com/sun/star/awt/DeviceCapability.hpp>
40
#include <com/sun/star/awt/XWindow.hpp>
41
#include <com/sun/star/rendering/CanvasFactory.hpp>
42
#include <com/sun/star/rendering/XSpriteCanvas.hpp>
43
44
#ifdef DISABLE_DYNLOADING
45
// Linking all needed LO code into one .so/executable, these already
46
// exist in the tools library, so put them in the anonymous namespace
47
// here to avoid clash...
48
namespace {
49
#endif
50
#ifdef DISABLE_DYNLOADING
51
}
52
#endif
53
54
using namespace ::com::sun::star::uno;
55
56
// Begin initializer and accessor public functions
57
58
OutputDevice::OutputDevice(OutDevType eOutDevType) :
59
1.91M
    meOutDevType(eOutDevType),
60
1.91M
    maRegion(true),
61
1.91M
    maFillColor( COL_WHITE ),
62
1.91M
    maTextLineColor( COL_TRANSPARENT ),
63
1.91M
    moSettings( Application::GetSettings() )
64
1.91M
{
65
1.91M
    mpGraphics                      = nullptr;
66
1.91M
    mpUnoGraphicsList               = nullptr;
67
1.91M
    mpPrevGraphics                  = nullptr;
68
1.91M
    mpNextGraphics                  = nullptr;
69
1.91M
    mpMetaFile                      = nullptr;
70
1.91M
    mpFontInstance                  = nullptr;
71
1.91M
    mpForcedFallbackInstance        = nullptr;
72
1.91M
    mpFontFaceCollection            = nullptr;
73
1.91M
    mpExtOutDevData                 = nullptr;
74
1.91M
    mnOutOffX                       = 0;
75
1.91M
    mnOutOffY                       = 0;
76
1.91M
    mnOutWidth                      = 0;
77
1.91M
    mnOutHeight                     = 0;
78
1.91M
    mnDPIX                          = 0;
79
1.91M
    mnDPIY                          = 0;
80
1.91M
    mnDPIScalePercentage            = 100;
81
1.91M
    mnTextOffX                      = 0;
82
1.91M
    mnTextOffY                      = 0;
83
1.91M
    mnOutOffOrigX                   = 0;
84
1.91M
    mnOutOffLogicX                  = 0;
85
1.91M
    mnOutOffOrigY                   = 0;
86
1.91M
    mnOutOffLogicY                  = 0;
87
1.91M
    mnEmphasisAscent                = 0;
88
1.91M
    mnEmphasisDescent               = 0;
89
1.91M
    mnDrawMode                      = DrawModeFlags::Default;
90
1.91M
    mnTextLayoutMode                = vcl::text::ComplexTextLayoutFlags::Default;
91
92
1.91M
    if( AllSettings::GetLayoutRTL() ) //#i84553# tip BiDi preference to RTL
93
0
        mnTextLayoutMode            = vcl::text::ComplexTextLayoutFlags::BiDiRtl | vcl::text::ComplexTextLayoutFlags::TextOriginLeft;
94
95
1.91M
    meOutDevViewType                = OutDevViewType::DontKnow;
96
1.91M
    mbMap                           = false;
97
1.91M
    mbClipRegion                    = false;
98
1.91M
    mbBackground                    = false;
99
1.91M
    mbOutput                        = true;
100
1.91M
    mbDevOutput                     = false;
101
1.91M
    mbOutputClipped                 = false;
102
1.91M
    maTextColor                     = COL_BLACK;
103
1.91M
    maOverlineColor                 = COL_TRANSPARENT;
104
1.91M
    meRasterOp                      = RasterOp::OverPaint;
105
1.91M
    mnAntialiasing                  = AntialiasingFlags::NONE;
106
1.91M
    meTextLanguage                  = LANGUAGE_SYSTEM;  // TODO: get default from configuration?
107
1.91M
    mbLineColor                     = true;
108
1.91M
    mbFillColor                     = true;
109
1.91M
    mbInitLineColor                 = true;
110
1.91M
    mbInitFillColor                 = true;
111
1.91M
    mbInitFont                      = true;
112
1.91M
    mbInitTextColor                 = true;
113
1.91M
    mbInitClipRegion                = true;
114
1.91M
    mbClipRegionSet                 = false;
115
1.91M
    mbNewFont                       = true;
116
1.91M
    mbTextLines                     = false;
117
1.91M
    mbTextSpecial                   = false;
118
1.91M
    mbRefPoint                      = false;
119
1.91M
    mbEnableRTL                     = false;    // mirroring must be explicitly allowed (typically for windows only)
120
1.91M
    mbSubpixelPositioning           = false; // tdf#168002 allow SubpixelPositioning (default: false)
121
122
    // struct ImplMapRes
123
1.91M
    maMapRes.mnMapOfsX              = 0;
124
1.91M
    maMapRes.mnMapOfsY              = 0;
125
1.91M
    maMapRes.mnMapScNumX            = 1;
126
1.91M
    maMapRes.mnMapScNumY            = 1;
127
1.91M
    maMapRes.mnMapScDenomX          = 1;
128
1.91M
    maMapRes.mnMapScDenomY          = 1;
129
130
    // struct ImplOutDevData- see #i82615#
131
1.91M
    mpOutDevData.reset(new ImplOutDevData);
132
1.91M
    mpOutDevData->mpRotateDev       = nullptr;
133
1.91M
    mpOutDevData->mpRecordLayout    = nullptr;
134
135
    // #i75163#
136
1.91M
    mpOutDevData->mpViewTransform   = nullptr;
137
1.91M
    mpOutDevData->mpInverseViewTransform = nullptr;
138
1.91M
}
139
140
OutputDevice::~OutputDevice()
141
1.88M
{
142
1.88M
    disposeOnce();
143
1.88M
}
144
145
void OutputDevice::dispose()
146
1.88M
{
147
1.88M
    if ( GetUnoGraphicsList() )
148
0
    {
149
0
        UnoWrapperBase* pWrapper = UnoWrapperBase::GetUnoWrapper( false );
150
0
        if ( pWrapper )
151
0
            pWrapper->ReleaseAllGraphics( this );
152
0
        delete mpUnoGraphicsList;
153
0
        mpUnoGraphicsList = nullptr;
154
0
    }
155
156
1.88M
    mpOutDevData->mpRotateDev.disposeAndClear();
157
158
    // #i75163#
159
1.88M
    ImplInvalidateViewTransform();
160
161
1.88M
    mpOutDevData.reset();
162
163
    // for some reason, we haven't removed state from the stack properly
164
1.88M
    if ( !maOutDevStateStack.empty() )
165
1.88M
        SAL_WARN( "vcl.gdi", "OutputDevice::~OutputDevice(): OutputDevice::Push() calls != OutputDevice::Pop() calls" );
166
1.88M
    maOutDevStateStack.clear();
167
168
    // release the active font instance
169
1.88M
    mpFontInstance.clear();
170
1.88M
    mpForcedFallbackInstance.clear();
171
172
    // remove cached results of GetDevFontList/GetDevSizeList
173
1.88M
    mpFontFaceCollection.reset();
174
175
    // release ImplFontCache specific to this OutputDevice
176
1.88M
    mxFontCache.reset();
177
178
    // release ImplFontList specific to this OutputDevice
179
1.88M
    mxFontCollection.reset();
180
181
1.88M
    mpPrevGraphics.reset();
182
1.88M
    mpNextGraphics.reset();
183
1.88M
    VclReferenceBase::dispose();
184
1.88M
}
185
186
bool OutputDevice::IsVirtual() const
187
0
{
188
0
    return false;
189
0
}
190
191
SalGraphics* OutputDevice::GetGraphics()
192
7.88k
{
193
7.88k
    DBG_TESTSOLARMUTEX();
194
195
7.88k
    if (!mpGraphics && !AcquireGraphics())
196
7.88k
        SAL_WARN("vcl.gdi", "No mpGraphics set");
197
198
7.88k
    return mpGraphics;
199
7.88k
}
200
201
SalGraphics const *OutputDevice::GetGraphics() const
202
0
{
203
0
    DBG_TESTSOLARMUTEX();
204
205
0
    if (!mpGraphics && !AcquireGraphics())
206
0
        SAL_WARN("vcl.gdi", "No mpGraphics set");
207
208
0
    return mpGraphics;
209
0
}
210
211
void OutputDevice::SetConnectMetaFile( GDIMetaFile* pMtf )
212
183k
{
213
183k
    mpMetaFile = pMtf;
214
183k
}
215
216
void OutputDevice::SetSettings( const AllSettings& rSettings )
217
48.3k
{
218
48.3k
    *moSettings = rSettings;
219
48.3k
}
220
221
SystemGraphicsData OutputDevice::GetSystemGfxData() const
222
12
{
223
12
    if (!mpGraphics && !AcquireGraphics())
224
0
        return SystemGraphicsData();
225
12
    assert(mpGraphics);
226
227
12
#if USE_HEADLESS_CODE
228
12
    if (OUTDEV_WINDOW == GetOutDevType())
229
12
        mpGraphics->ApplyFullDamage();
230
12
#endif
231
232
12
    return mpGraphics->GetGraphicsData();
233
12
}
234
235
OUString OutputDevice::GetRenderBackendName() const
236
0
{
237
0
    if (!mpGraphics && !AcquireGraphics())
238
0
        return {};
239
0
    assert(mpGraphics);
240
241
0
    return mpGraphics->getRenderBackendName();
242
0
}
243
244
#if ENABLE_CAIRO_CANVAS
245
246
bool OutputDevice::SupportsCairo() const
247
{
248
    if (!mpGraphics && !AcquireGraphics())
249
        return false;
250
    assert(mpGraphics);
251
252
    return mpGraphics->SupportsCairo();
253
}
254
255
cairo::SurfaceSharedPtr OutputDevice::CreateSurface(const cairo::CairoSurfaceSharedPtr& rSurface) const
256
{
257
    if (!mpGraphics && !AcquireGraphics())
258
        return cairo::SurfaceSharedPtr();
259
    assert(mpGraphics);
260
    return mpGraphics->CreateSurface(rSurface);
261
}
262
263
cairo::SurfaceSharedPtr OutputDevice::CreateSurface(int x, int y, int width, int height) const
264
{
265
    if (!mpGraphics && !AcquireGraphics())
266
        return cairo::SurfaceSharedPtr();
267
    assert(mpGraphics);
268
    return mpGraphics->CreateSurface(*this, x, y, width, height);
269
}
270
271
cairo::SurfaceSharedPtr OutputDevice::CreateBitmapSurface(const BitmapSystemData& rData, const Size& rSize) const
272
{
273
    if (!mpGraphics && !AcquireGraphics())
274
        return cairo::SurfaceSharedPtr();
275
    assert(mpGraphics);
276
    return mpGraphics->CreateBitmapSurface(*this, rData, rSize);
277
}
278
279
css::uno::Any OutputDevice::GetNativeSurfaceHandle(cairo::SurfaceSharedPtr& rSurface, const basegfx::B2ISize& rSize) const
280
{
281
    if (!mpGraphics && !AcquireGraphics())
282
        return css::uno::Any();
283
    assert(mpGraphics);
284
    return mpGraphics->GetNativeSurfaceHandle(rSurface, rSize);
285
}
286
287
#endif // ENABLE_CAIRO_CANVAS
288
289
css::uno::Any OutputDevice::GetSystemGfxDataAny() const
290
4
{
291
4
    const SystemGraphicsData aSysData = GetSystemGfxData();
292
4
    css::uno::Sequence< sal_Int8 > aSeq( reinterpret_cast<sal_Int8 const *>(&aSysData),
293
4
                                                      aSysData.nSize );
294
295
4
    return css::uno::Any(aSeq);
296
4
}
297
298
void OutputDevice::SetRefPoint()
299
515k
{
300
515k
    if ( mpMetaFile )
301
0
        mpMetaFile->AddAction( new MetaRefPointAction( Point(), false ) );
302
303
515k
    mbRefPoint = false;
304
515k
    maRefPoint.setX(0);
305
515k
    maRefPoint.setY(0);
306
515k
}
307
308
void OutputDevice::SetRefPoint( const Point& rRefPoint )
309
4.71k
{
310
4.71k
    if ( mpMetaFile )
311
4
        mpMetaFile->AddAction( new MetaRefPointAction( rRefPoint, true ) );
312
313
4.71k
    mbRefPoint = true;
314
4.71k
    maRefPoint = rRefPoint;
315
4.71k
}
316
317
void OutputDevice::SetRasterOp( RasterOp eRasterOp )
318
524k
{
319
524k
    if ( mpMetaFile )
320
14.5k
        mpMetaFile->AddAction( new MetaRasterOpAction( eRasterOp ) );
321
322
524k
    if ( meRasterOp != eRasterOp )
323
15.4k
    {
324
15.4k
        meRasterOp = eRasterOp;
325
15.4k
        mbInitLineColor = mbInitFillColor = true;
326
327
15.4k
        if( mpGraphics || AcquireGraphics() )
328
15.4k
        {
329
15.4k
            assert(mpGraphics);
330
15.4k
            mpGraphics->SetXORMode( (RasterOp::Invert == meRasterOp) || (RasterOp::Xor == meRasterOp), RasterOp::Invert == meRasterOp );
331
15.4k
        }
332
15.4k
    }
333
524k
}
334
335
void OutputDevice::EnableOutput( bool bEnable )
336
347k
{
337
347k
    mbOutput = bEnable;
338
347k
}
339
340
void OutputDevice::SetAntialiasing( AntialiasingFlags nMode )
341
76.9k
{
342
76.9k
    if ( mnAntialiasing != nMode )
343
560
    {
344
560
        mnAntialiasing = nMode;
345
560
        mbInitFont = true;
346
347
560
        if (mpGraphics)
348
560
            mpGraphics->setAntiAlias(bool(mnAntialiasing & AntialiasingFlags::Enable));
349
560
    }
350
76.9k
}
351
352
void OutputDevice::SetDrawMode(DrawModeFlags nDrawMode)
353
307k
{
354
307k
    mnDrawMode = nDrawMode;
355
307k
}
356
357
sal_uInt16 OutputDevice::GetBitCount() const
358
1.75M
{
359
    // we need a graphics instance
360
1.75M
    if ( !mpGraphics && !AcquireGraphics() )
361
0
        return 0;
362
1.75M
    assert(mpGraphics);
363
364
1.75M
    return mpGraphics->GetBitCount();
365
1.75M
}
366
367
void OutputDevice::SetOutOffXPixel(tools::Long nOutOffX)
368
0
{
369
0
    mnOutOffX = nOutOffX;
370
0
}
371
372
void OutputDevice::SetOutOffYPixel(tools::Long nOutOffY)
373
0
{
374
0
    mnOutOffY = nOutOffY;
375
0
}
376
377
css::uno::Reference< css::awt::XGraphics > OutputDevice::CreateUnoGraphics()
378
0
{
379
0
    UnoWrapperBase* pWrapper = UnoWrapperBase::GetUnoWrapper();
380
0
    return pWrapper ? pWrapper->CreateGraphics( this ) : css::uno::Reference< css::awt::XGraphics >();
381
0
}
382
383
std::vector< VCLXGraphics* > *OutputDevice::CreateUnoGraphicsList()
384
0
{
385
0
    mpUnoGraphicsList = new std::vector< VCLXGraphics* >;
386
0
    return mpUnoGraphicsList;
387
0
}
388
389
// Helper public function
390
391
bool OutputDevice::SupportsOperation( OutDevSupportType eType ) const
392
0
{
393
0
    if( !mpGraphics && !AcquireGraphics() )
394
0
        return false;
395
0
    assert(mpGraphics);
396
0
    const bool bHasSupport = mpGraphics->supportsOperation( eType );
397
0
    return bHasSupport;
398
0
}
399
400
// Direct OutputDevice drawing public functions
401
402
void OutputDevice::DrawOutDev( const Point& rDestPt, const Size& rDestSize,
403
                               const Point& rSrcPt,  const Size& rSrcSize )
404
0
{
405
0
    if( ImplIsRecordLayout() )
406
0
        return;
407
408
0
    if ( RasterOp::Invert == meRasterOp )
409
0
    {
410
0
        DrawRect( tools::Rectangle( rDestPt, rDestSize ) );
411
0
        return;
412
0
    }
413
414
0
    if ( mpMetaFile )
415
0
    {
416
0
        const Bitmap aBmp( GetBitmap( rSrcPt, rSrcSize ) );
417
0
        mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) );
418
0
    }
419
420
0
    if ( !IsDeviceOutputNecessary() )
421
0
        return;
422
423
0
    if ( !mpGraphics && !AcquireGraphics() )
424
0
        return;
425
0
    assert(mpGraphics);
426
427
0
    if ( mbInitClipRegion )
428
0
        InitClipRegion();
429
430
0
    if ( mbOutputClipped )
431
0
        return;
432
433
0
    tools::Long nSrcWidth   = ImplLogicWidthToDevicePixel( rSrcSize.Width() );
434
0
    tools::Long nSrcHeight  = ImplLogicHeightToDevicePixel( rSrcSize.Height() );
435
0
    tools::Long nDestWidth  = ImplLogicWidthToDevicePixel( rDestSize.Width() );
436
0
    tools::Long nDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
437
438
0
    if (nSrcWidth && nSrcHeight && nDestWidth && nDestHeight)
439
0
    {
440
0
        SalTwoRect aPosAry(ImplLogicXToDevicePixel(rSrcPt.X()), ImplLogicYToDevicePixel(rSrcPt.Y()),
441
0
                           nSrcWidth, nSrcHeight,
442
0
                           ImplLogicXToDevicePixel(rDestPt.X()), ImplLogicYToDevicePixel(rDestPt.Y()),
443
0
                           nDestWidth, nDestHeight);
444
445
0
        AdjustTwoRect( aPosAry, GetOutputRectPixel() );
446
447
0
        if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
448
0
            mpGraphics->CopyBits(aPosAry, *this);
449
0
    }
450
0
}
451
452
void OutputDevice::DrawOutDev( const Point& rDestPt, const Size& rDestSize,
453
                               const Point& rSrcPt,  const Size& rSrcSize,
454
                               const OutputDevice& rOutDev )
455
0
{
456
0
    if ( ImplIsRecordLayout() )
457
0
        return;
458
459
0
    if ( RasterOp::Invert == meRasterOp )
460
0
    {
461
0
        DrawRect( tools::Rectangle( rDestPt, rDestSize ) );
462
0
        return;
463
0
    }
464
465
0
    if ( mpMetaFile )
466
0
    {
467
0
        const Bitmap aBmp(rOutDev.GetBitmap(rSrcPt, rSrcSize));
468
0
        mpMetaFile->AddAction(new MetaBmpExScaleAction(rDestPt, rDestSize, aBmp));
469
0
    }
470
471
0
    if ( !IsDeviceOutputNecessary() )
472
0
        return;
473
474
0
    if ( !mpGraphics && !AcquireGraphics() )
475
0
        return;
476
0
    assert(mpGraphics);
477
478
0
    if ( mbInitClipRegion )
479
0
        InitClipRegion();
480
481
0
    if ( mbOutputClipped )
482
0
        return;
483
484
0
    SalTwoRect aPosAry(rOutDev.ImplLogicXToDevicePixel(rSrcPt.X()),
485
0
                             rOutDev.ImplLogicYToDevicePixel(rSrcPt.Y()),
486
0
                             rOutDev.ImplLogicWidthToDevicePixel(rSrcSize.Width()),
487
0
                             rOutDev.ImplLogicHeightToDevicePixel(rSrcSize.Height()),
488
0
                             ImplLogicXToDevicePixel(rDestPt.X()),
489
0
                             ImplLogicYToDevicePixel(rDestPt.Y()),
490
0
                             ImplLogicWidthToDevicePixel(rDestSize.Width()),
491
0
                             ImplLogicHeightToDevicePixel(rDestSize.Height()));
492
493
    // if we have alpha, this will blend source over destination
494
0
    drawOutDevDirect(rOutDev, aPosAry);
495
0
}
496
497
void OutputDevice::CopyArea( const Point& rDestPt,
498
                             const Point& rSrcPt,  const Size& rSrcSize,
499
                             bool bWindowInvalidate )
500
0
{
501
0
    if ( ImplIsRecordLayout() )
502
0
        return;
503
504
0
    RasterOp eOldRop = GetRasterOp();
505
0
    SetRasterOp( RasterOp::OverPaint );
506
507
0
    if ( !IsDeviceOutputNecessary() )
508
0
        return;
509
510
0
    if ( !mpGraphics && !AcquireGraphics() )
511
0
        return;
512
0
    assert(mpGraphics);
513
514
0
    if ( mbInitClipRegion )
515
0
        InitClipRegion();
516
517
0
    if ( mbOutputClipped )
518
0
        return;
519
520
0
    tools::Long nSrcWidth   = ImplLogicWidthToDevicePixel( rSrcSize.Width() );
521
0
    tools::Long nSrcHeight  = ImplLogicHeightToDevicePixel( rSrcSize.Height() );
522
0
    if (nSrcWidth && nSrcHeight)
523
0
    {
524
0
        SalTwoRect aPosAry(ImplLogicXToDevicePixel(rSrcPt.X()), ImplLogicYToDevicePixel(rSrcPt.Y()),
525
0
                           nSrcWidth, nSrcHeight,
526
0
                           ImplLogicXToDevicePixel(rDestPt.X()), ImplLogicYToDevicePixel(rDestPt.Y()),
527
0
                           nSrcWidth, nSrcHeight);
528
529
0
        AdjustTwoRect( aPosAry, GetOutputRectPixel() );
530
531
0
        CopyDeviceArea( aPosAry, bWindowInvalidate );
532
0
    }
533
534
0
    SetRasterOp( eOldRop );
535
0
}
536
537
// Direct OutputDevice drawing protected function
538
539
void OutputDevice::CopyDeviceArea( SalTwoRect& aPosAry, bool /*bWindowInvalidate*/)
540
0
{
541
0
    if (aPosAry.mnSrcWidth == 0 || aPosAry.mnSrcHeight == 0 || aPosAry.mnDestWidth == 0 || aPosAry.mnDestHeight == 0)
542
0
        return;
543
544
0
    aPosAry.mnDestWidth  = aPosAry.mnSrcWidth;
545
0
    aPosAry.mnDestHeight = aPosAry.mnSrcHeight;
546
0
    mpGraphics->CopyBits(aPosAry, *this);
547
0
}
548
549
// Direct OutputDevice drawing private function
550
void OutputDevice::drawOutDevDirect(const OutputDevice& rSrcDev, SalTwoRect& rPosAry)
551
0
{
552
0
    SalGraphics* pSrcGraphics;
553
0
    if (const OutputDevice* pCheckedSrc = DrawOutDevDirectCheck(rSrcDev))
554
0
    {
555
0
        if (!pCheckedSrc->mpGraphics && !pCheckedSrc->AcquireGraphics())
556
0
            return;
557
0
        pSrcGraphics = pCheckedSrc->mpGraphics;
558
0
    }
559
0
    else
560
0
        pSrcGraphics = nullptr;
561
562
0
    if (!mpGraphics && !AcquireGraphics())
563
0
        return;
564
0
    assert(mpGraphics);
565
566
    // #102532# Offset only has to be pseudo window offset
567
568
0
    AdjustTwoRect( rPosAry, rSrcDev.GetOutputRectPixel() );
569
570
0
    if ( rPosAry.mnSrcWidth && rPosAry.mnSrcHeight && rPosAry.mnDestWidth && rPosAry.mnDestHeight )
571
0
    {
572
        // if this is no window, but rSrcDev is a window
573
        // mirroring may be required
574
        // because only windows have a SalGraphicsLayout
575
        // mirroring is performed here
576
0
        DrawOutDevDirectProcess(rSrcDev, rPosAry, pSrcGraphics);
577
0
    }
578
0
}
579
580
const OutputDevice* OutputDevice::DrawOutDevDirectCheck(const OutputDevice& rSrcDev) const
581
0
{
582
0
    return this == &rSrcDev ? nullptr : &rSrcDev;
583
0
}
584
585
void OutputDevice::DrawOutDevDirectProcess(const OutputDevice& rSrcDev, SalTwoRect& rPosAry, SalGraphics* pSrcGraphics)
586
0
{
587
0
    if( pSrcGraphics && (pSrcGraphics->GetLayout() & SalLayoutFlags::BiDiRtl) )
588
0
    {
589
0
        SalTwoRect aPosAry2 = rPosAry;
590
0
        pSrcGraphics->mirror( aPosAry2.mnSrcX, aPosAry2.mnSrcWidth, rSrcDev );
591
0
        mpGraphics->CopyBits( aPosAry2, *pSrcGraphics, *this, rSrcDev );
592
0
        return;
593
0
    }
594
0
    if (pSrcGraphics)
595
0
        mpGraphics->CopyBits( rPosAry, *pSrcGraphics, *this, rSrcDev );
596
0
    else
597
0
        mpGraphics->CopyBits( rPosAry, *this );
598
0
}
599
600
tools::Rectangle OutputDevice::GetBackgroundComponentBounds() const
601
0
{
602
0
    return tools::Rectangle( Point( 0, 0 ), GetOutputSizePixel() );
603
0
}
604
605
// Layout public functions
606
607
void OutputDevice::EnableRTL( bool bEnable )
608
10.3k
{
609
10.3k
    mbEnableRTL = bEnable;
610
10.3k
}
611
612
bool OutputDevice::ImplIsAntiparallel() const
613
55.7k
{
614
55.7k
    bool bRet = false;
615
55.7k
    if( AcquireGraphics() )
616
55.7k
    {
617
55.7k
        if( ( (mpGraphics->GetLayout() & SalLayoutFlags::BiDiRtl) && ! IsRTLEnabled() ) ||
618
55.7k
            ( ! (mpGraphics->GetLayout() & SalLayoutFlags::BiDiRtl) && IsRTLEnabled() ) )
619
0
        {
620
0
            bRet = true;
621
0
        }
622
55.7k
    }
623
55.7k
    return bRet;
624
55.7k
}
625
626
// note: the coordinates to be remirrored are in frame coordinates !
627
628
void    OutputDevice::ReMirror( Point &rPoint ) const
629
0
{
630
0
    rPoint.setX( mnOutOffX + mnOutWidth - 1 - rPoint.X() + mnOutOffX );
631
0
}
632
void    OutputDevice::ReMirror( tools::Rectangle &rRect ) const
633
0
{
634
0
    tools::Long nWidth = rRect.Right() - rRect.Left();
635
636
    //long lc_x = rRect.nLeft - mnOutOffX;    // normalize
637
    //lc_x = mnOutWidth - nWidth - 1 - lc_x;  // mirror
638
    //rRect.nLeft = lc_x + mnOutOffX;         // re-normalize
639
640
0
    rRect.SetLeft( mnOutOffX + mnOutWidth - nWidth - 1 - rRect.Left() + mnOutOffX );
641
0
    rRect.SetRight( rRect.Left() + nWidth );
642
0
}
643
644
void OutputDevice::ReMirror( vcl::Region &rRegion ) const
645
0
{
646
0
    RectangleVector aRectangles;
647
0
    rRegion.GetRegionRectangles(aRectangles);
648
0
    vcl::Region aMirroredRegion;
649
650
0
    for (auto & rectangle : aRectangles)
651
0
    {
652
0
        ReMirror(rectangle);
653
0
        aMirroredRegion.Union(rectangle);
654
0
    }
655
656
0
    rRegion = std::move(aMirroredRegion);
657
658
0
}
659
660
bool OutputDevice::HasMirroredGraphics() const
661
115k
{
662
115k
   return ( AcquireGraphics() && (mpGraphics->GetLayout() & SalLayoutFlags::BiDiRtl) );
663
115k
}
664
665
bool OutputDevice::ImplIsRecordLayout() const
666
3.96M
{
667
3.96M
    if (!mpOutDevData)
668
0
        return false;
669
670
3.96M
    return mpOutDevData->mpRecordLayout;
671
3.96M
}
672
673
css::awt::DeviceInfo OutputDevice::GetCommonDeviceInfo(Size const& rDevSz) const
674
34.3k
{
675
34.3k
    css::awt::DeviceInfo aInfo;
676
677
34.3k
    aInfo.Width = rDevSz.Width();
678
34.3k
    aInfo.Height = rDevSz.Height();
679
680
34.3k
    Size aTmpSz = LogicToPixel(Size(1000, 1000), MapMode(MapUnit::MapMM));
681
34.3k
    aInfo.PixelPerMeterX = aTmpSz.Width();
682
34.3k
    aInfo.PixelPerMeterY = aTmpSz.Height();
683
34.3k
    aInfo.BitsPerPixel = GetBitCount();
684
685
34.3k
    aInfo.Capabilities = css::awt::DeviceCapability::RASTEROPERATIONS |
686
34.3k
        css::awt::DeviceCapability::GETBITS;
687
688
34.3k
    return aInfo;
689
34.3k
}
690
691
css::awt::DeviceInfo OutputDevice::GetDeviceInfo() const
692
0
{
693
0
    css::awt::DeviceInfo aInfo = GetCommonDeviceInfo(GetOutputSizePixel());
694
695
0
    aInfo.LeftInset = 0;
696
0
    aInfo.TopInset = 0;
697
0
    aInfo.RightInset = 0;
698
0
    aInfo.BottomInset = 0;
699
700
0
    return aInfo;
701
0
}
702
703
Reference< css::rendering::XCanvas > OutputDevice::GetCanvas() const
704
4
{
705
    // try to retrieve hard reference from weak member
706
4
    Reference< css::rendering::XCanvas > xCanvas( mxCanvas );
707
    // canvas still valid? Then we're done.
708
4
    if( xCanvas.is() )
709
0
        return xCanvas;
710
4
    xCanvas = ImplGetCanvas( false );
711
4
    mxCanvas = xCanvas;
712
4
    return xCanvas;
713
4
}
714
715
Reference< css::rendering::XSpriteCanvas > OutputDevice::GetSpriteCanvas() const
716
0
{
717
0
    Reference< css::rendering::XCanvas > xCanvas( mxCanvas );
718
0
    Reference< css::rendering::XSpriteCanvas > xSpriteCanvas( xCanvas, UNO_QUERY );
719
0
    if( xSpriteCanvas.is() )
720
0
        return xSpriteCanvas;
721
0
    xCanvas = ImplGetCanvas( true );
722
0
    mxCanvas = xCanvas;
723
0
    return Reference< css::rendering::XSpriteCanvas >( xCanvas, UNO_QUERY );
724
0
}
725
726
// Generic implementation, Window will override.
727
css::uno::Reference< css::rendering::XCanvas > OutputDevice::ImplGetCanvas( bool bSpriteCanvas ) const
728
0
{
729
    /* Arguments:
730
       0: ptr to creating instance (Window or VirtualDevice)
731
       1: current bounds of creating instance
732
       2: bool, denoting always on top state for Window (always false for VirtualDevice)
733
       3: XWindow for creating Window (or empty for VirtualDevice)
734
       4: SystemGraphicsData as a streamed Any
735
     */
736
0
    Sequence< Any > aArg{
737
0
        Any(reinterpret_cast<sal_Int64>(this)),
738
0
        Any(css::awt::Rectangle( mnOutOffX, mnOutOffY, mnOutWidth, mnOutHeight )),
739
0
        Any(false),
740
0
        Any(Reference< css::awt::XWindow >()),
741
0
        GetSystemGfxDataAny()
742
0
    };
743
744
0
    const Reference< XComponentContext >& xContext = comphelper::getProcessComponentContext();
745
746
0
    static tools::DeleteUnoReferenceOnDeinit<css::lang::XMultiComponentFactory> xStaticCanvasFactory(
747
0
        css::rendering::CanvasFactory::create( xContext ) );
748
0
    Reference<css::lang::XMultiComponentFactory> xCanvasFactory(xStaticCanvasFactory.get());
749
0
    Reference< css::rendering::XCanvas > xCanvas;
750
751
0
    if(xCanvasFactory.is())
752
0
    {
753
0
        xCanvas.set( xCanvasFactory->createInstanceWithArgumentsAndContext(
754
0
                         bSpriteCanvas ?
755
0
                         u"com.sun.star.rendering.SpriteCanvas"_ustr :
756
0
                         u"com.sun.star.rendering.Canvas"_ustr,
757
0
                         aArg,
758
0
                         xContext ),
759
0
                     UNO_QUERY );
760
0
    }
761
762
    // no factory??? Empty reference, then.
763
0
    return xCanvas;
764
0
}
765
766
void OutputDevice::ImplDisposeCanvas()
767
106k
{
768
106k
    css::uno::Reference< css::rendering::XCanvas > xCanvas( mxCanvas );
769
106k
    if( xCanvas.is() )
770
0
    {
771
0
        css::uno::Reference< css::lang::XComponent >  xCanvasComponent( xCanvas, css::uno::UNO_QUERY );
772
0
        if( xCanvasComponent.is() )
773
0
            xCanvasComponent->dispose();
774
0
    }
775
106k
}
776
777
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */