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