Coverage Report

Created: 2026-11-06 11:29

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