1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <hintids.hxx>
21 #include <tools/urlobj.hxx>
22 #include <vcl/imapobj.hxx>
23 #include <vcl/imap.hxx>
24 #include <svl/urihelper.hxx>
25 #include <sfx2/progress.hxx>
26 #include <sfx2/printer.hxx>
27 #include <editeng/udlnitem.hxx>
28 #include <editeng/colritem.hxx>
29 #include <editeng/boxitem.hxx>
31 #include <fmtsrnd.hxx>
36 #include <IDocumentSettingAccess.hxx>
37 #include <IDocumentStylePoolAccess.hxx>
38 #include <IDocumentDeviceAccess.hxx>
39 #include <IDocumentLayoutAccess.hxx>
41 #include <flyfrms.hxx>
42 #include <frmtool.hxx>
43 #include <viewopt.hxx>
44 #include <viewimp.hxx>
47 #include <rootfrm.hxx>
48 #include <dflyobj.hxx>
49 #include <pagefrm.hxx>
50 #include <notxtfrm.hxx>
52 #include <charatr.hxx>
53 #include <ndnotxt.hxx>
56 #include <swregion.hxx>
57 #include <poolfmt.hxx>
58 #include <strings.hrc>
59 #include <accessibilityoptions.hxx>
60 #include <com/sun/star/embed/EmbedMisc.hpp>
61 #include <com/sun/star/embed/EmbedStates.hpp>
62 #include <com/sun/star/embed/XEmbeddedObject.hpp>
63 #include <svtools/embedhlp.hxx>
65 #include <basegfx/matrix/b2dhommatrix.hxx>
66 #include <drawinglayer/processor2d/baseprocessor2d.hxx>
67 #include <drawinglayer/primitive2d/graphicprimitive2d.hxx>
68 #include <basegfx/matrix/b2dhommatrixtools.hxx>
69 #include <basegfx/utils/b2dclipstate.hxx>
70 #include <drawinglayer/processor2d/processor2dtools.hxx>
72 #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
73 #include <drawinglayer/primitive2d/objectinfoprimitive2d.hxx>
74 #include <osl/diagnose.h>
76 // MM02 needed for VOC mechanism and getting the OC - may be moved to an own file
77 #include <svx/sdrpagewindow.hxx>
78 #include <svx/svdpagv.hxx>
79 #include <svx/sdr/contact/viewcontact.hxx>
80 #include <svx/sdr/contact/viewobjectcontact.hxx>
81 #include <svx/sdr/contact/objectcontact.hxx>
82 #include <svx/sdr/contact/displayinfo.hxx>
84 using namespace com::sun::star
;
86 static bool GetRealURL( const SwGrfNode
& rNd
, OUString
& rText
)
88 bool bRet
= rNd
.GetFileFilterNms( &rText
, nullptr );
90 rText
= URIHelper::removePassword( rText
, INetURLObject::EncodeMechanism::WasEncoded
,
91 INetURLObject::DecodeMechanism::Unambiguous
);
92 if (rText
.startsWith("data:image")) rText
= "inline image";
97 static void lcl_PaintReplacement( const SwRect
&rRect
, const OUString
&rText
,
98 const SwViewShell
&rSh
, const SwNoTextFrame
*pFrame
,
101 static vcl::Font aFont
= []()
104 tmp
.SetWeight( WEIGHT_BOLD
);
105 tmp
.SetStyleName( OUString() );
106 tmp
.SetFamilyName("Noto Sans");
107 tmp
.SetFamily( FAMILY_SWISS
);
108 tmp
.SetTransparent( true );
112 Color
aCol( COL_RED
);
113 FontLineStyle eUnderline
= LINESTYLE_NONE
;
114 const SwFormatURL
&rURL
= pFrame
->FindFlyFrame()->GetFormat()->GetURL();
115 if( !rURL
.GetURL().isEmpty() || rURL
.GetMap() )
117 bool bVisited
= false;
120 ImageMap
*pMap
= const_cast<ImageMap
*>(rURL
.GetMap());
121 for( size_t i
= 0; i
< pMap
->GetIMapObjectCount(); ++i
)
123 IMapObject
*pObj
= pMap
->GetIMapObject( i
);
124 if( rSh
.GetDoc()->IsVisitedURL( pObj
->GetURL() ) )
131 else if ( !rURL
.GetURL().isEmpty() )
132 bVisited
= rSh
.GetDoc()->IsVisitedURL( rURL
.GetURL() );
134 SwFormat
*pFormat
= rSh
.GetDoc()->getIDocumentStylePoolAccess().GetFormatFromPool( o3tl::narrowing
<sal_uInt16
>
135 (bVisited
? RES_POOLCHR_INET_VISIT
: RES_POOLCHR_INET_NORMAL
) );
136 aCol
= pFormat
->GetColor().GetValue();
137 eUnderline
= pFormat
->GetUnderline().GetLineStyle();
140 aFont
.SetUnderline( eUnderline
);
141 aFont
.SetColor( aCol
);
143 const BitmapEx
& rBmp
= const_cast<SwViewShell
&>(rSh
).GetReplacementBitmap(bDefect
);
144 Graphic::DrawEx(*rSh
.GetOut(), rText
, aFont
, rBmp
, rRect
.Pos(), rRect
.SSize());
147 SwNoTextFrame::SwNoTextFrame(SwNoTextNode
* const pNode
, SwFrame
* pSib
)
148 : SwContentFrame( pNode
, pSib
)
150 mnFrameType
= SwFrameType::NoTxt
;
153 SwContentFrame
*SwNoTextNode::MakeFrame( SwFrame
* pSib
)
155 return new SwNoTextFrame(this, pSib
);
158 void SwNoTextFrame::DestroyImpl()
162 SwContentFrame::DestroyImpl();
165 SwNoTextFrame::~SwNoTextFrame()
169 void SetOutDev( SwViewShell
*pSh
, OutputDevice
*pOut
)
174 static void lcl_ClearArea( const SwFrame
&rFrame
,
175 vcl::RenderContext
&rOut
, const SwRect
& rPtArea
,
176 const SwRect
&rGrfArea
)
178 SwRegionRects
aRegion( rPtArea
, 4 );
181 if ( aRegion
.empty() )
184 const SvxBrushItem
*pItem
;
185 std::optional
<Color
> xCol
;
187 drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFillAttributes
;
189 if ( rFrame
.GetBackgroundBrush( aFillAttributes
, pItem
, xCol
, aOrigRect
, false, /*bConsiderTextBox=*/false ) )
191 SwRegionRects
const region(rPtArea
);
192 basegfx::utils::B2DClipState aClipState
;
193 const bool bDone(::DrawFillAttributes(aFillAttributes
, aOrigRect
, region
, aClipState
, rOut
));
197 for( const auto &rRegion
: aRegion
)
199 ::DrawGraphic(pItem
, rOut
, aOrigRect
, rRegion
);
205 rOut
.Push( vcl::PushFlags::FILLCOLOR
|vcl::PushFlags::LINECOLOR
);
206 rOut
.SetFillColor( rFrame
.getRootFrame()->GetCurrShell()->Imp()->GetRetoucheColor());
208 for( const auto &rRegion
: aRegion
)
209 rOut
.DrawRect( rRegion
.SVRect() );
214 void SwNoTextFrame::PaintSwFrame(vcl::RenderContext
& rRenderContext
, SwRect
const& rRect
, SwPrintData
const*const) const
216 if ( getFrameArea().IsEmpty() )
219 const SwViewShell
* pSh
= getRootFrame()->GetCurrShell();
220 if( !pSh
->GetViewOptions()->IsGraphic() )
223 // #i6467# - no paint of placeholder for page preview
224 if ( pSh
->GetWin() && !pSh
->IsPreview() )
226 const SwNoTextNode
* pNd
= GetNode()->GetNoTextNode();
227 OUString
aText( pNd
->GetTitle() );
228 if ( aText
.isEmpty() && pNd
->IsGrfNode() )
229 GetRealURL( *static_cast<const SwGrfNode
*>(pNd
), aText
);
230 if( aText
.isEmpty() )
231 aText
= FindFlyFrame()->GetFormat()->GetName();
232 lcl_PaintReplacement( getFrameArea(), aText
, *pSh
, this, false );
237 if( pSh
->GetAccessibilityOptions()->IsStopAnimatedGraphics() ||
238 // #i9684# Stop animation during printing/pdf export
242 SfxProgress::EnterLock(); // No progress reschedules in paint (SwapIn)
244 rRenderContext
.Push();
246 tools::PolyPolygon aPoly
;
248 SwNoTextNode
& rNoTNd
= const_cast<SwNoTextNode
&>(*static_cast<const SwNoTextNode
*>(GetNode()));
249 SwGrfNode
* pGrfNd
= rNoTNd
.GetGrfNode();
251 pGrfNd
->SetFrameInPaint( true );
253 // #i13147# - add 2nd parameter with value <true> to
254 // method call <FindFlyFrame().GetContour(..)> to indicate that it is called
255 // for paint in order to avoid load of the intrinsic graphic.
256 if ( ( !rRenderContext
.GetConnectMetaFile() ||
258 FindFlyFrame()->GetContour( aPoly
, true )
261 rRenderContext
.SetClipRegion(vcl::Region(aPoly
));
265 SwRect
aOrigPaint( rRect
);
266 if ( HasAnimation() && pSh
->GetWin() )
268 aOrigPaint
= getFrameArea(); aOrigPaint
+= getFramePrintArea().Pos();
271 SwRect
aGrfArea( getFrameArea() );
272 SwRect
aPaintArea( aGrfArea
);
274 // In case the picture fly frm was clipped, render it with the origin
275 // size instead of scaling it
276 if ( pGrfNd
&& rNoTNd
.getIDocumentSettingAccess()->get( DocumentSettingId::CLIPPED_PICTURES
) )
278 auto pFindFly
= FindFlyFrame();
279 if (pFindFly
&& pFindFly
->IsFlyFreeFrame())
281 const SwFlyFreeFrame
*pFly
= static_cast< const SwFlyFreeFrame
* >( pFindFly
);
282 bool bGetUnclippedFrame
=true;
283 const SvxBoxItem
* pBoxItem
;
284 if( pFly
->GetFormat() && (pBoxItem
= pFly
->GetFormat()->GetItemIfSet(RES_BOX
, false)) )
286 if( pBoxItem
->HasBorder( /*bTreatPaddingAsBorder*/true) )
287 bGetUnclippedFrame
= false;
290 if( bGetUnclippedFrame
)
291 aGrfArea
= SwRect( getFrameArea().Pos( ), pFly
->GetUnclippedFrame( ).SSize( ) );
295 aPaintArea
.Intersection_( aOrigPaint
);
297 SwRect
aNormal( getFrameArea().Pos() + getFramePrintArea().Pos(), getFramePrintArea().SSize() );
298 aNormal
.Justify(); // Normalized rectangle for the comparisons
300 if( aPaintArea
.Overlaps( aNormal
) )
302 // Calculate the four to-be-deleted rectangles
304 ::lcl_ClearArea( *this, rRenderContext
, aPaintArea
, aNormal
);
306 // The intersection of the PaintArea and the Bitmap contains the absolutely visible area of the Frame
307 aPaintArea
.Intersection_( aNormal
);
310 rRenderContext
.IntersectClipRegion( aPaintArea
.SVRect() );
311 /// delete unused 3rd parameter
312 PaintPicture( &rRenderContext
, aGrfArea
);
315 // If it's not visible, simply delete the given Area
316 lcl_ClearArea( *this, rRenderContext
, aPaintArea
, SwRect() );
318 pGrfNd
->SetFrameInPaint( false );
320 rRenderContext
.Pop();
321 SfxProgress::LeaveLock();
324 /** Calculate the position and the size of the graphic in the Frame,
325 corresponding to the current graphic attributes
327 @param Point the position in the Frame (also returned)
328 @param Size the graphic's size (also returned)
329 @param nMirror the current mirror attribute
331 static void lcl_CalcRect( Point
& rPt
, Size
& rDim
, MirrorGraph nMirror
)
333 if( nMirror
== MirrorGraph::Vertical
|| nMirror
== MirrorGraph::Both
)
335 rPt
.setX(rPt
.getX() + rDim
.Width() -1);
336 rDim
.setWidth( -rDim
.Width() );
339 if( nMirror
== MirrorGraph::Horizontal
|| nMirror
== MirrorGraph::Both
)
341 rPt
.setY(rPt
.getY() + rDim
.Height() -1);
342 rDim
.setHeight( -rDim
.Height() );
346 /** Calculate the Bitmap's position and the size within the passed rectangle */
347 void SwNoTextFrame::GetGrfArea( SwRect
&rRect
, SwRect
* pOrigRect
) const
349 // Currently only used for scaling, cropping and mirroring the contour of graphics!
350 // Everything else is handled by GraphicObject
351 // We put the graphic's visible rectangle into rRect.
352 // pOrigRect contains position and size of the whole graphic.
354 // RotateFlyFrame3: SwFrame may be transformed. Get untransformed
355 // SwRect(s) as base of calculation
356 const TransformableSwFrame
* pTransformableSwFrame(getTransformableSwFrame());
357 const SwRect
aFrameArea(pTransformableSwFrame
? pTransformableSwFrame
->getUntransformedFrameArea() : getFrameArea());
358 const SwRect
aFramePrintArea(pTransformableSwFrame
? pTransformableSwFrame
->getUntransformedFramePrintArea() : getFramePrintArea());
360 const SwAttrSet
& rAttrSet
= GetNode()->GetSwAttrSet();
361 const SwCropGrf
& rCrop
= rAttrSet
.GetCropGrf();
362 MirrorGraph nMirror
= rAttrSet
.GetMirrorGrf().GetValue();
364 if( rAttrSet
.GetMirrorGrf().IsGrfToggle() )
366 if( !(FindPageFrame()->GetVirtPageNum() % 2) )
370 case MirrorGraph::Dont
: nMirror
= MirrorGraph::Vertical
; break;
371 case MirrorGraph::Vertical
: nMirror
= MirrorGraph::Dont
; break;
372 case MirrorGraph::Horizontal
: nMirror
= MirrorGraph::Both
; break;
373 default: nMirror
= MirrorGraph::Horizontal
; break;
378 // We read graphic from the Node, if needed.
379 // It may fail, however.
380 tools::Long nLeftCrop
, nRightCrop
, nTopCrop
, nBottomCrop
;
381 Size
aOrigSz( static_cast<const SwNoTextNode
*>(GetNode())->GetTwipSize() );
382 if ( !aOrigSz
.Width() )
384 aOrigSz
.setWidth( aFramePrintArea
.Width() );
385 nLeftCrop
= -rCrop
.GetLeft();
386 nRightCrop
= -rCrop
.GetRight();
390 nLeftCrop
= std::max( aOrigSz
.Width() -
391 (rCrop
.GetRight() + rCrop
.GetLeft()), tools::Long(1) );
392 const double nScale
= double(aFramePrintArea
.Width()) / double(nLeftCrop
);
393 nLeftCrop
= tools::Long(nScale
* -rCrop
.GetLeft() );
394 nRightCrop
= tools::Long(nScale
* -rCrop
.GetRight() );
397 // crop values have to be mirrored too
398 if( nMirror
== MirrorGraph::Vertical
|| nMirror
== MirrorGraph::Both
)
400 tools::Long nTmpCrop
= nLeftCrop
;
401 nLeftCrop
= nRightCrop
;
402 nRightCrop
= nTmpCrop
;
405 if( !aOrigSz
.Height() )
407 aOrigSz
.setHeight( aFramePrintArea
.Height() );
408 nTopCrop
= -rCrop
.GetTop();
409 nBottomCrop
= -rCrop
.GetBottom();
413 nTopCrop
= std::max( aOrigSz
.Height() - (rCrop
.GetTop() + rCrop
.GetBottom()), tools::Long(1) );
414 const double nScale
= double(aFramePrintArea
.Height()) / double(nTopCrop
);
415 nTopCrop
= tools::Long(nScale
* -rCrop
.GetTop() );
416 nBottomCrop
= tools::Long(nScale
* -rCrop
.GetBottom() );
419 // crop values have to be mirrored too
420 if( nMirror
== MirrorGraph::Horizontal
|| nMirror
== MirrorGraph::Both
)
422 tools::Long nTmpCrop
= nTopCrop
;
423 nTopCrop
= nBottomCrop
;
424 nBottomCrop
= nTmpCrop
;
427 Size
aVisSz( aFramePrintArea
.SSize() );
428 Size
aGrfSz( aVisSz
);
429 Point
aVisPt( aFrameArea
.Pos() + aFramePrintArea
.Pos() );
430 Point
aGrfPt( aVisPt
);
432 // Set the "visible" rectangle first
435 aVisPt
.setX(aVisPt
.getX() + nLeftCrop
);
436 aVisSz
.AdjustWidth( -nLeftCrop
);
440 aVisPt
.setY(aVisPt
.getY() + nTopCrop
);
441 aVisSz
.AdjustHeight( -nTopCrop
);
443 if ( nRightCrop
> 0 )
444 aVisSz
.AdjustWidth( -nRightCrop
);
445 if ( nBottomCrop
> 0 )
446 aVisSz
.AdjustHeight( -nBottomCrop
);
448 rRect
.Pos ( aVisPt
);
449 rRect
.SSize( aVisSz
);
451 // Calculate the whole graphic if needed
455 Size
aTmpSz( aGrfSz
);
456 aGrfPt
.setX(aGrfPt
.getX() + nLeftCrop
);
457 aTmpSz
.AdjustWidth( -(nLeftCrop
+ nRightCrop
) );
458 aGrfPt
.setY(aGrfPt
.getY() + nTopCrop
);
459 aTmpSz
.AdjustHeight( -(nTopCrop
+ nBottomCrop
) );
461 if( MirrorGraph::Dont
!= nMirror
)
462 lcl_CalcRect( aGrfPt
, aTmpSz
, nMirror
);
464 pOrigRect
->Pos ( aGrfPt
);
465 pOrigRect
->SSize( aTmpSz
);
468 /** By returning the surrounding Fly's size which equals the graphic's size */
469 const Size
& SwNoTextFrame::GetSize() const
471 // Return the Frame's size
472 const SwFrame
*pFly
= FindFlyFrame();
475 return pFly
->getFramePrintArea().SSize();
478 void SwNoTextFrame::MakeAll(vcl::RenderContext
* pRenderContext
)
480 // RotateFlyFrame3 - inner frame. Get rotation and check if used
481 const double fRotation(getLocalFrameRotation());
482 const bool bRotated(!basegfx::fTools::equalZero(fRotation
));
486 SwFlyFreeFrame
* pUpperFly(dynamic_cast< SwFlyFreeFrame
* >(GetUpper()));
490 if(!pUpperFly
->isFrameAreaDefinitionValid())
492 // RotateFlyFrame3: outer frame *needs* to be layouted first, force this by calling
493 // it's ::Calc directly
494 pUpperFly
->Calc(pRenderContext
);
497 // Reset outer frame to unrotated state. This is necessary to make the
498 // layouting below work as currently implemented in Writer. As expected
499 // using Transformations allows to do this on the fly due to all information
500 // being included there.
501 // The full solution would be to adapt the whole layouting
502 // process of Writer to take care of Transformations, but that
503 // is currently beyond scope
504 if(pUpperFly
->isTransformableSwFrame())
506 pUpperFly
->getTransformableSwFrame()->restoreFrameAreas();
510 // Re-layout may be partially (see all isFrameAreaDefinitionValid() flags),
511 // so resetting the local SwFrame(s) in the local SwFrameAreaDefinition is also
512 // needed (e.g. for PrintPreview).
513 // Reset to BoundAreas will be done below automatically
514 if(isTransformableSwFrame())
516 getTransformableSwFrame()->restoreFrameAreas();
520 SwContentNotify
aNotify( this );
521 SwBorderAttrAccess
aAccess( SwFrame::GetCache(), this );
522 const SwBorderAttrs
&rAttrs
= *aAccess
.Get();
524 while ( !isFrameAreaPositionValid() || !isFrameAreaSizeValid() || !isFramePrintAreaValid() )
528 if ( !isFrameAreaSizeValid() )
530 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
531 aFrm
.Width( GetUpper()->getFramePrintArea().Width() );
534 MakePrtArea( rAttrs
);
536 if ( !isFrameAreaSizeValid() )
538 setFrameAreaSizeValid(true);
539 Format(getRootFrame()->GetCurrShell()->GetOut());
543 // RotateFlyFrame3 - inner frame
546 SwFlyFreeFrame
* pUpperFly(dynamic_cast< SwFlyFreeFrame
* >(GetUpper()));
550 // restore outer frame back to Transformed state, that means
551 // set the SwFrameAreaDefinition(s) back to BoundAreas of
552 // the transformed SwFrame. All needed information is part
553 // of the already correctly created Transformations of the
554 // upper frame, so it can be re-created on the fly
555 if(pUpperFly
->isTransformableSwFrame())
557 pUpperFly
->getTransformableSwFrame()->adaptFrameAreasToTransformations();
561 // After the unrotated layout is finished, apply possible set rotation to it
562 // get center from outer frame (layout frame) to be on the safe side
563 const Point
aCenter(GetUpper() ? GetUpper()->getFrameArea().Center() : getFrameArea().Center());
564 const basegfx::B2DPoint
aB2DCenter(aCenter
.X(), aCenter
.Y());
566 if(!mpTransformableSwFrame
)
568 mpTransformableSwFrame
.reset(new TransformableSwFrame(*this));
571 getTransformableSwFrame()->createFrameAreaTransformations(
574 getTransformableSwFrame()->adaptFrameAreasToTransformations();
578 // reset transformations to show that they are not used
579 mpTransformableSwFrame
.reset();
583 // RotateFlyFrame3 - Support for Transformations - outer frame
584 basegfx::B2DHomMatrix
SwNoTextFrame::getFrameAreaTransformation() const
586 if(isTransformableSwFrame())
588 // use pre-created transformation
589 return getTransformableSwFrame()->getLocalFrameAreaTransformation();
593 return SwContentFrame::getFrameAreaTransformation();
596 basegfx::B2DHomMatrix
SwNoTextFrame::getFramePrintAreaTransformation() const
598 if(isTransformableSwFrame())
600 // use pre-created transformation
601 return getTransformableSwFrame()->getLocalFramePrintAreaTransformation();
605 return SwContentFrame::getFramePrintAreaTransformation();
608 // RotateFlyFrame3 - Support for Transformations
609 void SwNoTextFrame::transform_translate(const Point
& rOffset
)
611 // call parent - this will do the basic transform for SwRect(s)
612 // in the SwFrameAreaDefinition
613 SwContentFrame::transform_translate(rOffset
);
615 // check if the Transformations need to be adapted
616 if(isTransformableSwFrame())
618 const basegfx::B2DHomMatrix
aTransform(
619 basegfx::utils::createTranslateB2DHomMatrix(
620 rOffset
.X(), rOffset
.Y()));
622 // transform using TransformableSwFrame
623 getTransformableSwFrame()->transform(aTransform
);
627 // RotateFlyFrame3 - inner frame
628 // Check if we contain a SwGrfNode and get possible rotation from it
629 double SwNoTextFrame::getLocalFrameRotation() const
631 const SwNoTextNode
* pSwNoTextNode(nullptr != GetNode() ? GetNode()->GetNoTextNode() : nullptr);
633 if(nullptr != pSwNoTextNode
)
635 const SwGrfNode
* pSwGrfNode(pSwNoTextNode
->GetGrfNode());
637 if(nullptr != pSwGrfNode
)
639 const SwAttrSet
& rSwAttrSet(pSwGrfNode
->GetSwAttrSet());
640 const SwRotationGrf
& rSwRotationGrf(rSwAttrSet
.GetRotationGrf());
641 const double fRotate
= -toRadians(rSwRotationGrf
.GetValue());
643 return basegfx::normalizeToRange(fRotate
, 2 * M_PI
);
651 /** Calculate the Bitmap's site, if needed */
652 void SwNoTextFrame::Format( vcl::RenderContext
* /*pRenderContext*/, const SwBorderAttrs
* )
654 const Size
aNewSize( GetSize() );
656 // Did the height change?
657 SwTwips nChgHght
= IsVertical() ?
658 static_cast<SwTwips
>(aNewSize
.Width() - getFramePrintArea().Width()) :
659 static_cast<SwTwips
>(aNewSize
.Height() - getFramePrintArea().Height());
662 else if( nChgHght
< 0)
663 Shrink( std::min(getFramePrintArea().Height(), tools::Long(-nChgHght
)) );
666 bool SwNoTextFrame::GetCharRect( SwRect
&rRect
, const SwPosition
& rPos
,
667 SwCursorMoveState
*pCMS
, bool /*bAllowFarAway*/ ) const
669 if ( &rPos
.GetNode() != static_cast<SwNode
const *>(GetNode()) )
672 Calc(getRootFrame()->GetCurrShell()->GetOut());
673 SwRect
aFrameRect( getFrameArea() );
675 rRect
.Pos( getFrameArea().Pos() + getFramePrintArea().Pos() );
676 rRect
.SSize( getFramePrintArea().SSize() );
680 // Is the Bitmap in the visible area at all?
681 if( !aFrameRect
.Overlaps( rRect
) )
683 // If not, then the Cursor is on the Frame
688 rRect
.Intersection_( aFrameRect
);
690 if ( pCMS
&& pCMS
->m_bRealHeight
)
692 pCMS
->m_aRealHeight
.setY(rRect
.Height());
693 pCMS
->m_aRealHeight
.setX(0);
699 bool SwNoTextFrame::GetModelPositionForViewPoint(SwPosition
* pPos
, Point
& ,
700 SwCursorMoveState
*, bool ) const
702 pPos
->Assign(*GetNode());
706 void SwNoTextFrame::ClearCache()
708 SwFlyFrame
* pFly
= FindFlyFrame();
709 if( pFly
&& pFly
->GetFormat()->GetSurround().IsContour() )
711 ClrContourCache( pFly
->GetVirtDrawObj() );
712 pFly
->NotifyBackground( FindPageFrame(), getFramePrintArea(), PrepareHint::FlyFrameAttributesChanged
);
716 void SwNoTextFrame::OnGraphicArrived()
718 if(GetNode()->GetNodeType() != SwNodeType::Grf
)
724 SwGrfNode
* pNd
= static_cast<SwGrfNode
*>(GetNode());
726 auto pVSh
= pNd
->GetDoc().getIDocumentLayoutAccess().GetCurrentViewShell();
728 pVSh
->OnGraphicArrived(getFrameArea());
731 void SwNoTextFrame::SwClientNotify(const SwModify
& rModify
, const SfxHint
& rHint
)
733 if(dynamic_cast<const sw::GrfRereadAndInCacheHint
*>(&rHint
))
735 if(SwNodeType::Grf
!= GetNode()->GetNodeType())
742 if(rHint
.GetId() == SfxHintId::SwPreGraphicArrived
743 || rHint
.GetId() == SfxHintId::SwGraphicPieceArrived
744 || rHint
.GetId() == SfxHintId::SwLinkedGraphicStreamArrived
)
749 else if (rHint
.GetId() != SfxHintId::SwLegacyModify
)
751 auto pLegacy
= static_cast<const sw::LegacyModifyHint
*>(&rHint
);
752 sal_uInt16 nWhich
= pLegacy
->GetWhich();
754 SwContentFrame::SwClientNotify(rModify
, rHint
);
756 bool bComplete
= true;
760 case RES_OBJECTDYING
:
763 case RES_UPDATE_ATTR
:
764 if (GetNode()->GetNodeType() != SwNodeType::Grf
) {
772 case RES_ATTRSET_CHG
:
775 for( n
= RES_GRFATR_BEGIN
; n
< RES_GRFATR_END
; ++n
)
776 if( SfxItemState::SET
== static_cast<const SwAttrSetChg
*>(pLegacy
->m_pOld
)->GetChgSet()->
777 GetItemState( n
, false ))
781 if(RES_GRFATR_ROTATION
== n
)
783 // RotGrfFlyFrame: Update Handles in view, these may be rotation-dependent
784 // (e.g. crop handles) and need a visualisation update
785 if ( GetNode()->GetNodeType() == SwNodeType::Grf
)
787 SwGrfNode
* pNd
= static_cast<SwGrfNode
*>( GetNode());
788 SwViewShell
*pVSh
= pNd
->GetDoc().getIDocumentLayoutAccess().GetCurrentViewShell();
792 SdrView
* pDrawView
= pVSh
->GetDrawView();
796 pDrawView
->AdjustMarkHdl(nullptr);
800 // RotateFlyFrame3 - invalidate needed for ContentFrame (inner, this)
801 // and LayoutFrame (outer, GetUpper). It is possible to only invalidate
802 // the outer frame, but that leads to an in-between state that gets
803 // potentially painted
806 GetUpper()->InvalidateAll_();
814 if( RES_GRFATR_END
== n
) // not found
820 if ( !pLegacy
->m_pNew
|| !isGRFATR(nWhich
) )
831 static void lcl_correctlyAlignRect( SwRect
& rAlignedGrfArea
, const SwRect
& rInArea
, vcl::RenderContext
const * pOut
)
836 tools::Rectangle aPxRect
= pOut
->LogicToPixel( rInArea
.SVRect() );
837 tools::Rectangle
aNewPxRect( aPxRect
);
838 while( aNewPxRect
.Left() < aPxRect
.Left() )
840 rAlignedGrfArea
.AddLeft( 1 );
841 aNewPxRect
= pOut
->LogicToPixel( rAlignedGrfArea
.SVRect() );
843 while( aNewPxRect
.Top() < aPxRect
.Top() )
845 rAlignedGrfArea
.AddTop(+1);
846 aNewPxRect
= pOut
->LogicToPixel( rAlignedGrfArea
.SVRect() );
848 while( aNewPxRect
.Bottom() > aPxRect
.Bottom() )
850 rAlignedGrfArea
.AddBottom( -1 );
851 aNewPxRect
= pOut
->LogicToPixel( rAlignedGrfArea
.SVRect() );
853 while( aNewPxRect
.Right() > aPxRect
.Right() )
855 rAlignedGrfArea
.AddRight(-1);
856 aNewPxRect
= pOut
->LogicToPixel( rAlignedGrfArea
.SVRect() );
860 static bool paintUsingPrimitivesHelper(
861 vcl::RenderContext
& rOutputDevice
,
862 const drawinglayer::primitive2d::Primitive2DContainer
& rSequence
,
863 const basegfx::B2DRange
& rSourceRange
,
864 const basegfx::B2DRange
& rTargetRange
)
866 if(!rSequence
.empty() && !basegfx::fTools::equalZero(rSourceRange
.getWidth()) && !basegfx::fTools::equalZero(rSourceRange
.getHeight()))
868 if(!basegfx::fTools::equalZero(rTargetRange
.getWidth()) && !basegfx::fTools::equalZero(rTargetRange
.getHeight()))
870 // map graphic range to target range. This will e.g. automatically include
871 // the mapping from 1/100th mm content to twips if needed when the target
872 // range is defined in twips
873 const basegfx::B2DHomMatrix
aMappingTransform(
874 basegfx::utils::createSourceRangeTargetRangeTransform(
878 // Fill ViewInformation. Use MappingTransform here, so there is no need to
879 // embed the primitives to it. Use original TargetRange here so there is also
880 // no need to embed the primitives to a MaskPrimitive for cropping. This works
881 // only in this case where the graphic object cannot be rotated, though.
882 drawinglayer::geometry::ViewInformation2D aViewInformation2D
;
883 aViewInformation2D
.setObjectTransformation(aMappingTransform
);
884 aViewInformation2D
.setViewTransformation(rOutputDevice
.GetViewTransformation());
885 aViewInformation2D
.setViewport(rTargetRange
);
887 // get a primitive processor for rendering
888 std::unique_ptr
<drawinglayer::processor2d::BaseProcessor2D
> pProcessor2D(
889 drawinglayer::processor2d::createProcessor2DFromOutputDevice(
890 rOutputDevice
, aViewInformation2D
) );
892 // render and cleanup
893 pProcessor2D
->process(rSequence
);
901 // MM02 original using fallback to VOC and primitive-based version
902 void paintGraphicUsingPrimitivesHelper(
903 vcl::RenderContext
& rOutputDevice
,
904 GraphicObject
const& rGrfObj
,
905 GraphicAttr
const& rGraphicAttr
,
906 const basegfx::B2DHomMatrix
& rGraphicTransform
,
907 const OUString
& rName
,
908 const OUString
& rTitle
,
909 const OUString
& rDescription
)
911 // RotGrfFlyFrame: unify using GraphicPrimitive2D
912 // -> the primitive handles all crop and mirror stuff
913 // -> the primitive renderer will create the needed pdf export data
914 // -> if bitmap content, it will be cached system-dependent
915 drawinglayer::primitive2d::Primitive2DContainer
aContent(1);
916 aContent
[0] = new drawinglayer::primitive2d::GraphicPrimitive2D(
921 // MM02 use primitive-based version for visualization
922 paintGraphicUsingPrimitivesHelper(
931 // MM02 new VOC and primitive-based version
932 void paintGraphicUsingPrimitivesHelper(
933 vcl::RenderContext
& rOutputDevice
,
934 drawinglayer::primitive2d::Primitive2DContainer
& rContent
,
935 const basegfx::B2DHomMatrix
& rGraphicTransform
,
936 const OUString
& rName
,
937 const OUString
& rTitle
,
938 const OUString
& rDescription
)
940 // RotateFlyFrame3: If ClipRegion is set at OutputDevice, we
941 // need to use that. Usually the renderer would be a VCL-based
942 // PrimitiveRenderer, but there are system-specific shortcuts that
943 // will *not* use the VCL-Paint of Bitmap and thus ignore this.
944 // Anyways, indirectly using a CLipRegion set at the target OutDev
945 // when using a PrimitiveRenderer is a non-valid implication.
946 // First tried only to use when HasPolyPolygonOrB2DPolyPolygon(),
947 // but there is an optimization at ClipRegion creation that detects
948 // a single Rectangle in a tools::PolyPolygon and forces to a simple
949 // RegionBand-based implementation, so cannot use it here.
950 if(rOutputDevice
.IsClipRegion())
952 basegfx::B2DPolyPolygon
aClip(rOutputDevice
.GetClipRegion().GetAsB2DPolyPolygon());
954 if(0 != aClip
.count())
958 new drawinglayer::primitive2d::MaskPrimitive2D(
960 drawinglayer::primitive2d::Primitive2DContainer(rContent
));
964 if(!rName
.isEmpty() || !rTitle
.isEmpty() || !rDescription
.isEmpty())
966 // Embed to ObjectInfoPrimitive2D when we have Name/Title/Description
967 // information available
970 new drawinglayer::primitive2d::ObjectInfoPrimitive2D(
971 drawinglayer::primitive2d::Primitive2DContainer(rContent
),
977 basegfx::B2DRange
aTargetRange(0.0, 0.0, 1.0, 1.0);
978 aTargetRange
.transform(rGraphicTransform
);
980 paintUsingPrimitivesHelper(
987 // DrawContact section
988 namespace { // anonymous namespace
989 class ViewObjectContactOfSwNoTextFrame
: public sdr::contact::ViewObjectContact
992 virtual void createPrimitive2DSequence(
993 const sdr::contact::DisplayInfo
& rDisplayInfo
,
994 drawinglayer::primitive2d::Primitive2DDecompositionVisitor
& rVisitor
) const override
;
996 // tdf#155190 disable this so superclass doesn't wrongly produce NonStruct
997 virtual bool isExportPDFTags() const override
{ return false; }
1000 ViewObjectContactOfSwNoTextFrame(
1001 sdr::contact::ObjectContact
& rObjectContact
,
1002 sdr::contact::ViewContact
& rViewContact
);
1005 class ViewContactOfSwNoTextFrame
: public sdr::contact::ViewContact
1009 const SwNoTextFrame
& mrSwNoTextFrame
;
1012 // Create an Object-Specific ViewObjectContact, set ViewContact and
1013 // ObjectContact. Always needs to return something.
1014 virtual sdr::contact::ViewObjectContact
& CreateObjectSpecificViewObjectContact(
1015 sdr::contact::ObjectContact
& rObjectContact
) override
;
1018 // read-access to owner
1019 const SwNoTextFrame
& getSwNoTextFrame() const { return mrSwNoTextFrame
; }
1021 // basic constructor, used from SwNoTextFrame.
1022 explicit ViewContactOfSwNoTextFrame(const SwNoTextFrame
& rSwNoTextFrame
);
1025 void ViewObjectContactOfSwNoTextFrame::createPrimitive2DSequence(
1026 const sdr::contact::DisplayInfo
& /*rDisplayInfo*/,
1027 drawinglayer::primitive2d::Primitive2DDecompositionVisitor
& rVisitor
) const
1029 // MM02 get all the parameters formally used in paintGraphicUsingPrimitivesHelper
1030 ViewContactOfSwNoTextFrame
& rVCOfNTF(static_cast<ViewContactOfSwNoTextFrame
&>(GetViewContact()));
1031 const SwNoTextFrame
& rSwNoTextFrame(rVCOfNTF
.getSwNoTextFrame());
1032 SwNoTextNode
& rNoTNd(const_cast<SwNoTextNode
&>(*static_cast<const SwNoTextNode
*>(rSwNoTextFrame
.GetNode())));
1033 SwGrfNode
* pGrfNd(rNoTNd
.GetGrfNode());
1035 if(nullptr != pGrfNd
)
1037 const bool bPrn(GetObjectContact().isOutputToPrinter() || GetObjectContact().isOutputToRecordingMetaFile());
1038 const GraphicObject
& rGrfObj(pGrfNd
->GetGrfObj(bPrn
));
1039 GraphicAttr aGraphicAttr
;
1040 pGrfNd
->GetGraphicAttr(aGraphicAttr
, &rSwNoTextFrame
);
1041 const basegfx::B2DHomMatrix
aGraphicTransform(rSwNoTextFrame
.getFrameAreaTransformation());
1043 // MM02 this is the right place in the VOC-Mechanism to create
1044 // the primitives for visualization - these will be automatically
1045 // buffered and reused
1046 rVisitor
.visit(new drawinglayer::primitive2d::GraphicPrimitive2D(
1053 ViewObjectContactOfSwNoTextFrame::ViewObjectContactOfSwNoTextFrame(
1054 sdr::contact::ObjectContact
& rObjectContact
,
1055 sdr::contact::ViewContact
& rViewContact
)
1056 : sdr::contact::ViewObjectContact(rObjectContact
, rViewContact
)
1060 sdr::contact::ViewObjectContact
& ViewContactOfSwNoTextFrame::CreateObjectSpecificViewObjectContact(
1061 sdr::contact::ObjectContact
& rObjectContact
)
1063 sdr::contact::ViewObjectContact
* pRetval
= new ViewObjectContactOfSwNoTextFrame(rObjectContact
, *this);
1067 ViewContactOfSwNoTextFrame::ViewContactOfSwNoTextFrame(
1068 const SwNoTextFrame
& rSwNoTextFrame
1070 : mrSwNoTextFrame(rSwNoTextFrame
)
1073 } // end of anonymous namespace
1075 sdr::contact::ViewContact
& SwNoTextFrame::GetViewContact() const
1079 const_cast< SwNoTextFrame
* >(this)->mpViewContact
=
1080 std::make_unique
<ViewContactOfSwNoTextFrame
>(*this);
1083 return *mpViewContact
;
1086 /** Paint the graphic.
1088 We require either a QuickDraw-Bitmap or a graphic here. If we do not have
1089 either, we return a replacement.
1091 @todo use aligned rectangle for drawing graphic.
1092 @todo pixel-align coordinations for drawing graphic. */
1093 void SwNoTextFrame::PaintPicture( vcl::RenderContext
* pOut
, const SwRect
&rGrfArea
) const
1095 SwViewShell
* pShell
= getRootFrame()->GetCurrShell();
1097 SwNoTextNode
& rNoTNd
= const_cast<SwNoTextNode
&>(*static_cast<const SwNoTextNode
*>(GetNode()));
1098 SwGrfNode
* pGrfNd
= rNoTNd
.GetGrfNode();
1099 SwOLENode
* pOLENd
= rNoTNd
.GetOLENode();
1101 const bool bPrn
= pOut
== rNoTNd
.getIDocumentDeviceAccess().getPrinter( false ) ||
1102 pOut
->GetConnectMetaFile();
1104 const bool bIsChart
= pOLENd
&& pOLENd
->GetOLEObj().GetObject().IsChart();
1106 // calculate aligned rectangle from parameter <rGrfArea>.
1107 // Use aligned rectangle <aAlignedGrfArea> instead of <rGrfArea> in
1108 // the following code.
1109 SwRect aAlignedGrfArea
= rGrfArea
;
1110 ::SwAlignRect( aAlignedGrfArea
, pShell
, pOut
);
1114 // Because for drawing a graphic left-top-corner and size coordinations are
1115 // used, these coordinations have to be determined on pixel level.
1116 ::SwAlignGrfRect( &aAlignedGrfArea
, *pOut
);
1118 else //if( bIsChart )
1120 // #i78025# charts own borders are not completely visible
1121 // the above pixel correction is not correct - at least not for charts
1122 // so a different pixel correction is chosen here
1123 // this might be a good idea for all other OLE objects also,
1124 // but as I cannot oversee the consequences I fix it only for charts for now
1125 lcl_correctlyAlignRect( aAlignedGrfArea
, rGrfArea
, pOut
);
1130 // Fix for bug fdo#33781
1131 const AntialiasingFlags
nFormerAntialiasingAtOutput( pOut
->GetAntialiasing() );
1132 if (SwDrawView::IsAntiAliasing())
1133 pOut
->SetAntialiasing( nFormerAntialiasingAtOutput
| AntialiasingFlags::Enable
);
1135 ImplPaintPictureGraphic( pOut
, pGrfNd
, bPrn
, aAlignedGrfArea
, pShell
, rNoTNd
);
1137 if ( SwDrawView::IsAntiAliasing() )
1138 pOut
->SetAntialiasing( nFormerAntialiasingAtOutput
);
1140 else // bIsChart || pOLENd
1142 // Fix for bug fdo#33781
1143 const AntialiasingFlags
nFormerAntialiasingAtOutput( pOut
->GetAntialiasing() );
1144 if (SwDrawView::IsAntiAliasing())
1146 AntialiasingFlags nNewAntialiasingAtOutput
= nFormerAntialiasingAtOutput
| AntialiasingFlags::Enable
;
1149 // Adjust AntiAliasing mode at output device for chart OLE
1150 if ( pOLENd
->IsChart() )
1151 nNewAntialiasingAtOutput
|= AntialiasingFlags::PixelSnapHairline
;
1153 pOut
->SetAntialiasing( nNewAntialiasingAtOutput
);
1156 ImplPaintPictureBitmap( pOut
, pOLENd
, bIsChart
, bPrn
, aAlignedGrfArea
, pShell
);
1159 if (SwDrawView::IsAntiAliasing())
1161 pOut
->SetAntialiasing( nFormerAntialiasingAtOutput
);
1166 void SwNoTextFrame::ImplPaintPictureGraphic( vcl::RenderContext
* pOut
,
1167 SwGrfNode
* pGrfNd
, bool bPrn
,
1168 const SwRect
& rAlignedGrfArea
, SwViewShell
* pShell
,
1169 SwNoTextNode
& rNoTNd
) const
1171 bool bContinue
= true;
1172 const GraphicObject
& rGrfObj
= pGrfNd
->GetGrfObj(bPrn
);
1174 GraphicAttr aGrfAttr
;
1175 pGrfNd
->GetGraphicAttr( aGrfAttr
, this );
1180 if ( pGrfNd
->IsLinkedInputStreamReady() )
1182 pGrfNd
->UpdateLinkWithInputStream();
1184 // #i85717#, #i90395# - check, if asynchronous retrieval
1185 // if input stream for the graphic is possible
1186 else if ( ( rGrfObj
.GetType() == GraphicType::Default
||
1187 rGrfObj
.GetType() == GraphicType::NONE
) &&
1188 pGrfNd
->IsLinkedFile() &&
1189 pGrfNd
->IsAsyncRetrieveInputStreamPossible() )
1192 ::sfx2::SvLinkSource
* pGrfObj
= pGrfNd
->GetLink()->GetObj();
1194 !pGrfObj
->IsDataComplete() ||
1195 !(aTmpSz
= pGrfNd
->GetTwipSize()).Width() ||
1198 pGrfNd
->TriggerAsyncRetrieveInputStream(); // #i73788#
1200 OUString
aText( pGrfNd
->GetTitle() );
1201 if ( aText
.isEmpty() )
1202 GetRealURL( *pGrfNd
, aText
);
1203 ::lcl_PaintReplacement( rAlignedGrfArea
, aText
, *pShell
, this, false );
1211 if( !rGrfObj
.GetGraphic().IsSupportedGraphic())
1213 ImplPaintPictureReplacement(rGrfObj
, pGrfNd
, rAlignedGrfArea
, pShell
);
1217 const bool bAnimate
= rGrfObj
.IsAnimated() &&
1218 !pShell
->IsPreview() &&
1219 !pShell
->GetAccessibilityOptions()->IsStopAnimatedGraphics() &&
1220 // #i9684# Stop animation during printing/pdf export
1223 FindFlyFrame() != ::GetFlyFromMarked( nullptr, pShell
))
1225 ImplPaintPictureAnimate(pOut
, pShell
, pGrfNd
, rAlignedGrfArea
);
1229 // MM02 To allow system-dependent buffering of the involved
1230 // bitmaps it is necessary to re-use the involved primitives
1231 // and their already executed decomposition (also for
1232 // performance reasons). This is usually done in DrawingLayer
1233 // by using the VOC-Mechanism (see descriptions elsewhere).
1234 // To get that here, make the involved SwNoTextFrame (this)
1235 // a sdr::contact::ViewContact supplier by supporting
1236 // a GetViewContact() - call. For ObjectContact we can use
1237 // the already existing ObjectContact from the involved
1238 // DrawingLayer. For this, the helper classes
1239 // ViewObjectContactOfSwNoTextFrame
1240 // ViewContactOfSwNoTextFrame
1241 // are created which support the VOC-mechanism in its minimal
1242 // form. This allows automatic and view-dependent (multiple edit
1243 // windows, print, etc.) re-use of the created primitives.
1244 // Also: Will be very useful when completely changing the Writer
1245 // repaint to VOC and Primitives, too.
1246 static const char* pDisableMM02Goodies(getenv("SAL_DISABLE_MM02_GOODIES"));
1247 static bool bUseViewObjectContactMechanism(nullptr == pDisableMM02Goodies
);
1248 // tdf#130951 for safety reasons use fallback if ViewObjectContactMechanism
1249 // fails for some reason - usually could only be not to find the correct
1251 bool bSucceeded(false);
1253 if(bUseViewObjectContactMechanism
)
1255 // MM02 use VOC-mechanism and buffer primitives
1256 SwViewShellImp
* pImp(pShell
->Imp());
1257 SdrPageView
* pPageView(nullptr != pImp
1258 ? pImp
->GetPageView()
1260 // tdf#130951 caution - target may be Window, use the correct OutputDevice
1261 OutputDevice
* pTarget((pShell
->isOutputToWindow() && pShell
->GetWin())
1262 ? pShell
->GetWin()->GetOutDev()
1263 : pShell
->GetOut());
1264 SdrPageWindow
* pPageWindow(nullptr != pPageView
&& nullptr != pTarget
1265 ? pPageView
->FindPageWindow(*pTarget
)
1268 if(nullptr != pPageWindow
)
1270 sdr::contact::ObjectContact
& rOC(pPageWindow
->GetObjectContact());
1271 sdr::contact::ViewContact
& rVC(GetViewContact());
1272 sdr::contact::ViewObjectContact
& rVOC(rVC
.GetViewObjectContact(rOC
));
1273 sdr::contact::DisplayInfo aDisplayInfo
;
1275 drawinglayer::primitive2d::Primitive2DContainer
aPrimitives(rVOC
.getPrimitive2DSequence(aDisplayInfo
));
1276 const basegfx::B2DHomMatrix
aGraphicTransform(getFrameAreaTransformation());
1278 paintGraphicUsingPrimitivesHelper(
1282 nullptr == pGrfNd
->GetFlyFormat() ? OUString() : pGrfNd
->GetFlyFormat()->GetName(),
1284 rNoTNd
.GetDescription());
1291 // MM02 fallback to direct paint with primitive-recreation
1292 // which will block reusage of system-dependent bitmap data
1293 const basegfx::B2DHomMatrix
aGraphicTransform(getFrameAreaTransformation());
1295 paintGraphicUsingPrimitivesHelper(
1300 nullptr == pGrfNd
->GetFlyFormat() ? OUString() : pGrfNd
->GetFlyFormat()->GetName(),
1302 rNoTNd
.GetDescription());
1306 void SwNoTextFrame::ImplPaintPictureAnimate(vcl::RenderContext
* pOut
, SwViewShell
* pShell
,
1307 SwGrfNode
* pGrfNd
, const SwRect
& rAlignedGrfArea
) const
1309 OutputDevice
* pVout
;
1310 if( pOut
== pShell
->GetOut() && SwRootFrame::FlushVout() )
1313 pOut
= pShell
->GetOut();
1315 else if( pShell
->GetWin() && pOut
->IsVirtual() )
1318 pOut
= pShell
->GetWin()->GetOutDev();
1323 OSL_ENSURE( !pOut
->IsVirtual() ||
1324 pShell
->GetViewOptions()->IsPDFExport() || pShell
->isOutputToWindow(),
1325 "pOut should not be a virtual device" );
1327 pGrfNd
->StartGraphicAnimation(pOut
, rAlignedGrfArea
.Pos(),
1328 rAlignedGrfArea
.SSize(), reinterpret_cast<sal_IntPtr
>(this),
1332 void SwNoTextFrame::ImplPaintPictureReplacement(const GraphicObject
& rGrfObj
, SwGrfNode
* pGrfNd
,
1333 const SwRect
& rAlignedGrfArea
, SwViewShell
* pShell
) const
1337 if( GraphicType::NONE
== rGrfObj
.GetType() )
1338 pResId
= STR_COMCORE_READERROR
;
1339 else if ( !rGrfObj
.GetGraphic().IsSupportedGraphic() )
1340 pResId
= STR_COMCORE_CANT_SHOW
;
1344 (aText
= pGrfNd
->GetTitle()).isEmpty() &&
1345 (!GetRealURL( *pGrfNd
, aText
) || aText
.isEmpty()))
1347 pResId
= STR_COMCORE_READERROR
;
1350 aText
= SwResId(pResId
);
1352 ::lcl_PaintReplacement( rAlignedGrfArea
, aText
, *pShell
, this, true );
1355 void SwNoTextFrame::ImplPaintPictureBitmap( vcl::RenderContext
* pOut
,
1356 SwOLENode
* pOLENd
, bool bIsChart
, bool bPrn
, const SwRect
& rAlignedGrfArea
,
1357 SwViewShell
* pShell
) const
1363 basegfx::B2DRange aSourceRange
;
1364 const drawinglayer::primitive2d::Primitive2DContainer
aSequence(
1365 pOLENd
->GetOLEObj().tryToGetChartContentAsPrimitive2DSequence(
1369 if(!aSequence
.empty() && !aSourceRange
.isEmpty())
1371 const basegfx::B2DRange
aTargetRange(
1372 rAlignedGrfArea
.Left(), rAlignedGrfArea
.Top(),
1373 rAlignedGrfArea
.Right(), rAlignedGrfArea
.Bottom());
1375 bDone
= paintUsingPrimitivesHelper(
1383 if(bDone
|| !pOLENd
)
1386 // SwOLENode does not have a known GraphicObject, need to
1387 // work with Graphic instead
1388 const Graphic
* pGraphic
= pOLENd
->GetGraphic();
1389 const Point
aPosition(rAlignedGrfArea
.Pos());
1390 const Size
aSize(rAlignedGrfArea
.SSize());
1392 if ( pGraphic
&& pGraphic
->GetType() != GraphicType::NONE
)
1394 pGraphic
->Draw(*pOut
, aPosition
, aSize
);
1396 // shade the representation if the object is activated outplace
1397 uno::Reference
< embed::XEmbeddedObject
> xObj
= pOLENd
->GetOLEObj().GetOleRef();
1398 if ( xObj
.is() && xObj
->getCurrentState() == embed::EmbedStates::ACTIVE
)
1401 ::svt::EmbeddedObjectRef::DrawShading(
1410 ::svt::EmbeddedObjectRef::DrawPaintReplacement(
1411 tools::Rectangle(aPosition
, aSize
),
1412 pOLENd
->GetOLEObj().GetCurrentPersistName(),
1416 sal_Int64 nMiscStatus
= pOLENd
->GetOLEObj().GetOleRef()->getStatus( pOLENd
->GetAspect() );
1417 if ( !bPrn
&& dynamic_cast< const SwCursorShell
*>( pShell
) != nullptr &&
1418 (nMiscStatus
& embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE
))
1420 const SwFlyFrame
*pFly
= FindFlyFrame();
1421 assert( pFly
!= nullptr );
1422 static_cast<SwFEShell
*>(pShell
)->ConnectObj( pOLENd
->GetOLEObj().GetObject(), pFly
->getFramePrintArea(), pFly
->getFrameArea());
1426 bool SwNoTextFrame::IsTransparent() const
1428 const SwViewShell
* pSh
= getRootFrame()->GetCurrShell();
1430 if ( !pSh
|| !pSh
->GetViewOptions()->IsGraphic() )
1435 const SwGrfNode
*pNd
;
1437 if( nullptr != (pNd
= GetNode()->GetGrfNode()) )
1439 if(pNd
->IsTransparent())
1445 // RotateFlyFrame3: If we are transformed, there are 'free' areas between
1446 // the Graphic and the Border/Padding stuff - at least as long as those
1447 // (Border and Padding) are not transformed, too
1448 if(isTransformableSwFrame())
1450 // we can be more specific - rotations of multiples of
1451 // 90 degrees will leave no gaps. Go from [0.0 .. 2PI]
1452 // to [0 .. 360] and check modulo 90
1453 const tools::Long
nRot(static_cast<tools::Long
>(basegfx::rad2deg(getLocalFrameRotation())));
1454 const bool bMultipleOf90(0 == (nRot
% 90));
1462 //#29381# OLE are always transparent
1463 if(nullptr != GetNode()->GetOLENode())
1468 // return false by default to avoid background paint
1472 void SwNoTextFrame::StopAnimation( const OutputDevice
* pOut
) const
1474 // Stop animated graphics
1475 const SwGrfNode
* pGrfNd
= GetNode()->GetGrfNode();
1477 if( pGrfNd
&& pGrfNd
->IsAnimated() )
1479 const_cast< SwGrfNode
* >(pGrfNd
)->StopGraphicAnimation( pOut
, reinterpret_cast<sal_IntPtr
>(this) );
1483 bool SwNoTextFrame::HasAnimation() const
1485 const SwGrfNode
* pGrfNd
= GetNode()->GetGrfNode();
1486 return pGrfNd
&& pGrfNd
->IsAnimated();
1489 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */