/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: */ |