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/svdoutl.hxx>
79 #include <svx/svdpage.hxx>
80 #include <svx/svdpagv.hxx>
81 #include <svx/unopage.hxx>
82 #include <svx/sdr/contact/viewcontact.hxx>
83 #include <svx/sdr/contact/viewobjectcontact.hxx>
84 #include <svx/sdr/contact/objectcontact.hxx>
85 #include <svx/sdr/contact/displayinfo.hxx>
87 using namespace com::sun::star
;
89 static bool GetRealURL( const SwGrfNode
& rNd
, OUString
& rText
)
91 bool bRet
= rNd
.GetFileFilterNms( &rText
, nullptr );
93 rText
= URIHelper::removePassword( rText
, INetURLObject::EncodeMechanism::WasEncoded
,
94 INetURLObject::DecodeMechanism::Unambiguous
);
95 if (rText
.startsWith("data:image")) rText
= "inline image";
100 static void lcl_PaintReplacement( const SwRect
&rRect
, const OUString
&rText
,
101 const SwViewShell
&rSh
, const SwNoTextFrame
*pFrame
,
104 static vcl::Font aFont
= []()
107 tmp
.SetWeight( WEIGHT_BOLD
);
108 tmp
.SetStyleName( OUString() );
109 tmp
.SetFamilyName(u
"Noto Sans"_ustr
);
110 tmp
.SetFamily( FAMILY_SWISS
);
111 tmp
.SetTransparent( true );
115 Color
aCol( COL_RED
);
116 FontLineStyle eUnderline
= LINESTYLE_NONE
;
117 const SwFormatURL
&rURL
= pFrame
->FindFlyFrame()->GetFormat()->GetURL();
118 if( !rURL
.GetURL().isEmpty() || rURL
.GetMap() )
120 bool bVisited
= false;
123 ImageMap
*pMap
= const_cast<ImageMap
*>(rURL
.GetMap());
124 for( size_t i
= 0; i
< pMap
->GetIMapObjectCount(); ++i
)
126 IMapObject
*pObj
= pMap
->GetIMapObject( i
);
127 if( rSh
.GetDoc()->IsVisitedURL( pObj
->GetURL() ) )
134 else if ( !rURL
.GetURL().isEmpty() )
135 bVisited
= rSh
.GetDoc()->IsVisitedURL( rURL
.GetURL() );
137 SwFormat
*pFormat
= rSh
.GetDoc()->getIDocumentStylePoolAccess().GetFormatFromPool( o3tl::narrowing
<sal_uInt16
>
138 (bVisited
? RES_POOLCHR_INET_VISIT
: RES_POOLCHR_INET_NORMAL
) );
139 aCol
= pFormat
->GetColor().GetValue();
140 eUnderline
= pFormat
->GetUnderline().GetLineStyle();
143 aFont
.SetUnderline( eUnderline
);
144 aFont
.SetColor( aCol
);
146 const BitmapEx
& rBmp
= const_cast<SwViewShell
&>(rSh
).GetReplacementBitmap(bDefect
);
147 Graphic::DrawEx(*rSh
.GetOut(), rText
, aFont
, rBmp
, rRect
.Pos(), rRect
.SSize());
150 SwNoTextFrame::SwNoTextFrame(SwNoTextNode
* const pNode
, SwFrame
* pSib
)
151 : SwContentFrame( pNode
, pSib
)
153 mnFrameType
= SwFrameType::NoTxt
;
156 SwContentFrame
*SwNoTextNode::MakeFrame( SwFrame
* pSib
)
158 return new SwNoTextFrame(this, pSib
);
161 void SwNoTextFrame::DestroyImpl()
165 SwContentFrame::DestroyImpl();
168 SwNoTextFrame::~SwNoTextFrame()
172 void SetOutDev( SwViewShell
*pSh
, OutputDevice
*pOut
)
177 static void lcl_ClearArea( const SwFrame
&rFrame
,
178 vcl::RenderContext
&rOut
, const SwRect
& rPtArea
,
179 const SwRect
&rGrfArea
)
181 SwRegionRects
aRegion( rPtArea
, 4 );
184 if ( aRegion
.empty() )
187 const SvxBrushItem
*pItem
;
188 std::optional
<Color
> xCol
;
190 drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFillAttributes
;
192 if ( rFrame
.GetBackgroundBrush( aFillAttributes
, pItem
, xCol
, aOrigRect
, false, /*bConsiderTextBox=*/false ) )
194 SwRegionRects
const region(rPtArea
);
195 basegfx::utils::B2DClipState aClipState
;
196 const bool bDone(::DrawFillAttributes(aFillAttributes
, aOrigRect
, region
, aClipState
, rOut
));
200 for( const auto &rRegion
: aRegion
)
202 ::DrawGraphic(pItem
, rOut
, aOrigRect
, rRegion
);
208 rOut
.Push( vcl::PushFlags::FILLCOLOR
|vcl::PushFlags::LINECOLOR
);
209 rOut
.SetFillColor( rFrame
.getRootFrame()->GetCurrShell()->Imp()->GetRetoucheColor());
211 for( const auto &rRegion
: aRegion
)
212 rOut
.DrawRect( rRegion
.SVRect() );
217 void SwNoTextFrame::PaintSwFrame(vcl::RenderContext
& rRenderContext
, SwRect
const& rRect
, PaintFrameMode
) const
219 if ( getFrameArea().IsEmpty() )
222 const SwViewShell
* pSh
= getRootFrame()->GetCurrShell();
223 if( !pSh
->GetViewOptions()->IsGraphic() )
226 // #i6467# - no paint of placeholder for page preview
227 if ( pSh
->GetWin() && !pSh
->IsPreview() )
229 const SwNoTextNode
* pNd
= GetNode()->GetNoTextNode();
230 OUString
aText( pNd
->GetTitle() );
231 if ( aText
.isEmpty() && pNd
->IsGrfNode() )
232 GetRealURL( *static_cast<const SwGrfNode
*>(pNd
), aText
);
233 if( aText
.isEmpty() )
234 aText
= FindFlyFrame()->GetFormat()->GetName();
235 lcl_PaintReplacement( getFrameArea(), aText
, *pSh
, this, false );
240 if( pSh
->GetAccessibilityOptions()->IsStopAnimatedGraphics() ||
241 // #i9684# Stop animation during printing/pdf export
245 SfxProgress::EnterLock(); // No progress reschedules in paint (SwapIn)
247 rRenderContext
.Push();
249 tools::PolyPolygon aPoly
;
251 SwNoTextNode
& rNoTNd
= const_cast<SwNoTextNode
&>(*static_cast<const SwNoTextNode
*>(GetNode()));
252 SwGrfNode
* pGrfNd
= rNoTNd
.GetGrfNode();
254 pGrfNd
->SetFrameInPaint( true );
256 // #i13147# - add 2nd parameter with value <true> to
257 // method call <FindFlyFrame().GetContour(..)> to indicate that it is called
258 // for paint in order to avoid load of the intrinsic graphic.
259 if ( ( !rRenderContext
.GetConnectMetaFile() ||
261 FindFlyFrame()->GetContour( aPoly
, true )
264 // don't clip if related compatibility flag is set
265 const IDocumentSettingAccess
& rIDSA
= pSh
->GetDoc()->getIDocumentSettingAccess();
266 if (!rIDSA
.get(DocumentSettingId::NO_CLIPPING_WITH_WRAP_POLYGON
))
267 rRenderContext
.SetClipRegion(vcl::Region(aPoly
));
271 SwRect
aOrigPaint( rRect
);
272 if ( HasAnimation() && pSh
->GetWin() )
274 aOrigPaint
= getFrameArea(); aOrigPaint
+= getFramePrintArea().Pos();
277 SwRect
aGrfArea( getFrameArea() );
278 SwRect
aPaintArea( aGrfArea
);
280 // In case the picture fly frm was clipped, render it with the origin
281 // size instead of scaling it
282 if ( pGrfNd
&& rNoTNd
.getIDocumentSettingAccess()->get( DocumentSettingId::CLIPPED_PICTURES
) )
284 auto pFindFly
= FindFlyFrame();
285 if (pFindFly
&& pFindFly
->IsFlyFreeFrame())
287 const SwFlyFreeFrame
*pFly
= static_cast< const SwFlyFreeFrame
* >( pFindFly
);
288 bool bGetUnclippedFrame
=true;
289 const SvxBoxItem
* pBoxItem
;
290 if( pFly
->GetFormat() && (pBoxItem
= pFly
->GetFormat()->GetItemIfSet(RES_BOX
, false)) )
292 if( pBoxItem
->HasBorder( /*bTreatPaddingAsBorder*/true) )
293 bGetUnclippedFrame
= false;
296 if( bGetUnclippedFrame
)
297 aGrfArea
= SwRect( getFrameArea().Pos( ), pFly
->GetUnclippedFrame( ).SSize( ) );
301 aPaintArea
.Intersection_( aOrigPaint
);
303 SwRect
aNormal( getFrameArea().Pos() + getFramePrintArea().Pos(), getFramePrintArea().SSize() );
304 aNormal
.Justify(); // Normalized rectangle for the comparisons
306 if( aPaintArea
.Overlaps( aNormal
) )
308 // Calculate the four to-be-deleted rectangles
310 ::lcl_ClearArea( *this, rRenderContext
, aPaintArea
, aNormal
);
312 // The intersection of the PaintArea and the Bitmap contains the absolutely visible area of the Frame
313 aPaintArea
.Intersection_( aNormal
);
316 rRenderContext
.IntersectClipRegion( aPaintArea
.SVRect() );
317 /// delete unused 3rd parameter
318 PaintPicture( &rRenderContext
, aGrfArea
);
321 // If it's not visible, simply delete the given Area
322 lcl_ClearArea( *this, rRenderContext
, aPaintArea
, SwRect() );
324 pGrfNd
->SetFrameInPaint( false );
326 rRenderContext
.Pop();
327 SfxProgress::LeaveLock();
330 /** Calculate the position and the size of the graphic in the Frame,
331 corresponding to the current graphic attributes
333 @param Point the position in the Frame (also returned)
334 @param Size the graphic's size (also returned)
335 @param nMirror the current mirror attribute
337 static void lcl_CalcRect( Point
& rPt
, Size
& rDim
, MirrorGraph nMirror
)
339 if( nMirror
== MirrorGraph::Vertical
|| nMirror
== MirrorGraph::Both
)
341 rPt
.setX(rPt
.getX() + rDim
.Width() -1);
342 rDim
.setWidth( -rDim
.Width() );
345 if( nMirror
== MirrorGraph::Horizontal
|| nMirror
== MirrorGraph::Both
)
347 rPt
.setY(rPt
.getY() + rDim
.Height() -1);
348 rDim
.setHeight( -rDim
.Height() );
352 /** Calculate the Bitmap's position and the size within the passed rectangle */
353 void SwNoTextFrame::GetGrfArea( SwRect
&rRect
, SwRect
* pOrigRect
) const
355 // Currently only used for scaling, cropping and mirroring the contour of graphics!
356 // Everything else is handled by GraphicObject
357 // We put the graphic's visible rectangle into rRect.
358 // pOrigRect contains position and size of the whole graphic.
360 // RotateFlyFrame3: SwFrame may be transformed. Get untransformed
361 // SwRect(s) as base of calculation
362 const TransformableSwFrame
* pTransformableSwFrame(getTransformableSwFrame());
363 const SwRect
aFrameArea(pTransformableSwFrame
? pTransformableSwFrame
->getUntransformedFrameArea() : getFrameArea());
364 const SwRect
aFramePrintArea(pTransformableSwFrame
? pTransformableSwFrame
->getUntransformedFramePrintArea() : getFramePrintArea());
366 const SwAttrSet
& rAttrSet
= GetNode()->GetSwAttrSet();
367 const SwCropGrf
& rCrop
= rAttrSet
.GetCropGrf();
368 MirrorGraph nMirror
= rAttrSet
.GetMirrorGrf().GetValue();
370 if( rAttrSet
.GetMirrorGrf().IsGrfToggle() )
372 if( !(FindPageFrame()->GetVirtPageNum() % 2) )
376 case MirrorGraph::Dont
: nMirror
= MirrorGraph::Vertical
; break;
377 case MirrorGraph::Vertical
: nMirror
= MirrorGraph::Dont
; break;
378 case MirrorGraph::Horizontal
: nMirror
= MirrorGraph::Both
; break;
379 default: nMirror
= MirrorGraph::Horizontal
; break;
384 // We read graphic from the Node, if needed.
385 // It may fail, however.
386 tools::Long nLeftCrop
, nRightCrop
, nTopCrop
, nBottomCrop
;
387 Size
aOrigSz( static_cast<const SwNoTextNode
*>(GetNode())->GetTwipSize() );
388 if ( !aOrigSz
.Width() )
390 aOrigSz
.setWidth( aFramePrintArea
.Width() );
391 nLeftCrop
= -rCrop
.GetLeft();
392 nRightCrop
= -rCrop
.GetRight();
396 nLeftCrop
= std::max( aOrigSz
.Width() -
397 (rCrop
.GetRight() + rCrop
.GetLeft()), tools::Long(1) );
398 const double nScale
= double(aFramePrintArea
.Width()) / double(nLeftCrop
);
399 nLeftCrop
= tools::Long(nScale
* -rCrop
.GetLeft() );
400 nRightCrop
= tools::Long(nScale
* -rCrop
.GetRight() );
403 // crop values have to be mirrored too
404 if( nMirror
== MirrorGraph::Vertical
|| nMirror
== MirrorGraph::Both
)
406 tools::Long nTmpCrop
= nLeftCrop
;
407 nLeftCrop
= nRightCrop
;
408 nRightCrop
= nTmpCrop
;
411 if( !aOrigSz
.Height() )
413 aOrigSz
.setHeight( aFramePrintArea
.Height() );
414 nTopCrop
= -rCrop
.GetTop();
415 nBottomCrop
= -rCrop
.GetBottom();
419 nTopCrop
= std::max( aOrigSz
.Height() - (rCrop
.GetTop() + rCrop
.GetBottom()), tools::Long(1) );
420 const double nScale
= double(aFramePrintArea
.Height()) / double(nTopCrop
);
421 nTopCrop
= tools::Long(nScale
* -rCrop
.GetTop() );
422 nBottomCrop
= tools::Long(nScale
* -rCrop
.GetBottom() );
425 // crop values have to be mirrored too
426 if( nMirror
== MirrorGraph::Horizontal
|| nMirror
== MirrorGraph::Both
)
428 tools::Long nTmpCrop
= nTopCrop
;
429 nTopCrop
= nBottomCrop
;
430 nBottomCrop
= nTmpCrop
;
433 Size
aVisSz( aFramePrintArea
.SSize() );
434 Size
aGrfSz( aVisSz
);
435 Point
aVisPt( aFrameArea
.Pos() + aFramePrintArea
.Pos() );
436 Point
aGrfPt( aVisPt
);
438 // Set the "visible" rectangle first
441 aVisPt
.setX(aVisPt
.getX() + nLeftCrop
);
442 aVisSz
.AdjustWidth( -nLeftCrop
);
446 aVisPt
.setY(aVisPt
.getY() + nTopCrop
);
447 aVisSz
.AdjustHeight( -nTopCrop
);
449 if ( nRightCrop
> 0 )
450 aVisSz
.AdjustWidth( -nRightCrop
);
451 if ( nBottomCrop
> 0 )
452 aVisSz
.AdjustHeight( -nBottomCrop
);
454 rRect
.Pos ( aVisPt
);
455 rRect
.SSize( aVisSz
);
457 // Calculate the whole graphic if needed
461 Size
aTmpSz( aGrfSz
);
462 aGrfPt
.setX(aGrfPt
.getX() + nLeftCrop
);
463 aTmpSz
.AdjustWidth( -(nLeftCrop
+ nRightCrop
) );
464 aGrfPt
.setY(aGrfPt
.getY() + nTopCrop
);
465 aTmpSz
.AdjustHeight( -(nTopCrop
+ nBottomCrop
) );
467 if( MirrorGraph::Dont
!= nMirror
)
468 lcl_CalcRect( aGrfPt
, aTmpSz
, nMirror
);
470 pOrigRect
->Pos ( aGrfPt
);
471 pOrigRect
->SSize( aTmpSz
);
474 /** By returning the surrounding Fly's size which equals the graphic's size */
475 const Size
& SwNoTextFrame::GetSize() const
477 // Return the Frame's size
478 const SwFrame
*pFly
= FindFlyFrame();
481 return pFly
->getFramePrintArea().SSize();
484 void SwNoTextFrame::MakeAll(vcl::RenderContext
* pRenderContext
)
486 // RotateFlyFrame3 - inner frame. Get rotation and check if used
487 const double fRotation(getLocalFrameRotation());
488 const bool bRotated(!basegfx::fTools::equalZero(fRotation
));
492 SwFlyFreeFrame
* pUpperFly(dynamic_cast< SwFlyFreeFrame
* >(GetUpper()));
496 if(!pUpperFly
->isFrameAreaDefinitionValid())
498 // RotateFlyFrame3: outer frame *needs* to be layouted first, force this by calling
499 // it's ::Calc directly
500 pUpperFly
->Calc(pRenderContext
);
503 // Reset outer frame to unrotated state. This is necessary to make the
504 // layouting below work as currently implemented in Writer. As expected
505 // using Transformations allows to do this on the fly due to all information
506 // being included there.
507 // The full solution would be to adapt the whole layouting
508 // process of Writer to take care of Transformations, but that
509 // is currently beyond scope
510 if(pUpperFly
->isTransformableSwFrame())
512 pUpperFly
->getTransformableSwFrame()->restoreFrameAreas();
516 // Re-layout may be partially (see all isFrameAreaDefinitionValid() flags),
517 // so resetting the local SwFrame(s) in the local SwFrameAreaDefinition is also
518 // needed (e.g. for PrintPreview).
519 // Reset to BoundAreas will be done below automatically
520 if(isTransformableSwFrame())
522 getTransformableSwFrame()->restoreFrameAreas();
526 SwContentNotify
aNotify( this );
527 SwBorderAttrAccess
aAccess( SwFrame::GetCache(), this );
528 const SwBorderAttrs
&rAttrs
= *aAccess
.Get();
530 while ( !isFrameAreaPositionValid() || !isFrameAreaSizeValid() || !isFramePrintAreaValid() )
534 if ( !isFrameAreaSizeValid() )
536 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
537 aFrm
.Width( GetUpper()->getFramePrintArea().Width() );
540 MakePrtArea( rAttrs
);
542 if ( !isFrameAreaSizeValid() )
544 setFrameAreaSizeValid(true);
545 Format(getRootFrame()->GetCurrShell()->GetOut());
549 // RotateFlyFrame3 - inner frame
552 SwFlyFreeFrame
* pUpperFly(dynamic_cast< SwFlyFreeFrame
* >(GetUpper()));
556 // restore outer frame back to Transformed state, that means
557 // set the SwFrameAreaDefinition(s) back to BoundAreas of
558 // the transformed SwFrame. All needed information is part
559 // of the already correctly created Transformations of the
560 // upper frame, so it can be re-created on the fly
561 if(pUpperFly
->isTransformableSwFrame())
563 pUpperFly
->getTransformableSwFrame()->adaptFrameAreasToTransformations();
567 // After the unrotated layout is finished, apply possible set rotation to it
568 // get center from outer frame (layout frame) to be on the safe side
569 const Point
aCenter(GetUpper() ? GetUpper()->getFrameArea().Center() : getFrameArea().Center());
570 const basegfx::B2DPoint
aB2DCenter(aCenter
.X(), aCenter
.Y());
572 if(!mpTransformableSwFrame
)
574 mpTransformableSwFrame
.reset(new TransformableSwFrame(*this));
577 getTransformableSwFrame()->createFrameAreaTransformations(
580 getTransformableSwFrame()->adaptFrameAreasToTransformations();
584 // reset transformations to show that they are not used
585 mpTransformableSwFrame
.reset();
589 // RotateFlyFrame3 - Support for Transformations - outer frame
590 basegfx::B2DHomMatrix
SwNoTextFrame::getFrameAreaTransformation() const
592 if(isTransformableSwFrame())
594 // use pre-created transformation
595 return getTransformableSwFrame()->getLocalFrameAreaTransformation();
599 return SwContentFrame::getFrameAreaTransformation();
602 basegfx::B2DHomMatrix
SwNoTextFrame::getFramePrintAreaTransformation() const
604 if(isTransformableSwFrame())
606 // use pre-created transformation
607 return getTransformableSwFrame()->getLocalFramePrintAreaTransformation();
611 return SwContentFrame::getFramePrintAreaTransformation();
614 // RotateFlyFrame3 - Support for Transformations
615 void SwNoTextFrame::transform_translate(const Point
& rOffset
)
617 // call parent - this will do the basic transform for SwRect(s)
618 // in the SwFrameAreaDefinition
619 SwContentFrame::transform_translate(rOffset
);
621 // check if the Transformations need to be adapted
622 if(isTransformableSwFrame())
624 const basegfx::B2DHomMatrix
aTransform(
625 basegfx::utils::createTranslateB2DHomMatrix(
626 rOffset
.X(), rOffset
.Y()));
628 // transform using TransformableSwFrame
629 getTransformableSwFrame()->transform(aTransform
);
633 // RotateFlyFrame3 - inner frame
634 // Check if we contain a SwGrfNode and get possible rotation from it
635 double SwNoTextFrame::getLocalFrameRotation() const
637 const SwNoTextNode
* pSwNoTextNode(nullptr != GetNode() ? GetNode()->GetNoTextNode() : nullptr);
639 if(nullptr != pSwNoTextNode
)
641 const SwGrfNode
* pSwGrfNode(pSwNoTextNode
->GetGrfNode());
643 if(nullptr != pSwGrfNode
)
645 const SwAttrSet
& rSwAttrSet(pSwGrfNode
->GetSwAttrSet());
646 const SwRotationGrf
& rSwRotationGrf(rSwAttrSet
.GetRotationGrf());
647 const double fRotate
= -toRadians(rSwRotationGrf
.GetValue());
649 return basegfx::normalizeToRange(fRotate
, 2 * M_PI
);
657 void SwNoTextFrame::dumpAsXml(xmlTextWriterPtr writer
) const
659 (void)xmlTextWriterStartElement(writer
, reinterpret_cast<const xmlChar
*>("notxt"));
660 dumpAsXmlAttributes(writer
);
662 (void)xmlTextWriterStartElement(writer
, BAD_CAST("infos"));
663 dumpInfosAsXml(writer
);
664 (void)xmlTextWriterEndElement(writer
);
665 dumpChildrenAsXml(writer
);
667 (void)xmlTextWriterEndElement(writer
);
670 /** Calculate the Bitmap's site, if needed */
671 void SwNoTextFrame::Format( vcl::RenderContext
* /*pRenderContext*/, const SwBorderAttrs
* )
673 const Size
aNewSize( GetSize() );
675 // Did the height change?
676 SwTwips nChgHght
= IsVertical() ?
677 static_cast<SwTwips
>(aNewSize
.Width() - getFramePrintArea().Width()) :
678 static_cast<SwTwips
>(aNewSize
.Height() - getFramePrintArea().Height());
681 else if( nChgHght
< 0)
682 Shrink( std::min(getFramePrintArea().Height(), tools::Long(-nChgHght
)) );
685 bool SwNoTextFrame::GetCharRect( SwRect
&rRect
, const SwPosition
& rPos
,
686 SwCursorMoveState
*pCMS
, bool /*bAllowFarAway*/ ) const
688 if ( &rPos
.GetNode() != static_cast<SwNode
const *>(GetNode()) )
691 Calc(getRootFrame()->GetCurrShell()->GetOut());
692 SwRect
aFrameRect( getFrameArea() );
694 rRect
.Pos( getFrameArea().Pos() + getFramePrintArea().Pos() );
695 rRect
.SSize( getFramePrintArea().SSize() );
699 // Is the Bitmap in the visible area at all?
700 if( !aFrameRect
.Overlaps( rRect
) )
702 // If not, then the Cursor is on the Frame
707 rRect
.Intersection_( aFrameRect
);
709 if ( pCMS
&& pCMS
->m_bRealHeight
)
711 pCMS
->m_aRealHeight
.setY(rRect
.Height());
712 pCMS
->m_aRealHeight
.setX(0);
718 bool SwNoTextFrame::GetModelPositionForViewPoint(SwPosition
* pPos
, Point
& ,
719 SwCursorMoveState
*, bool ) const
721 pPos
->Assign(*GetNode());
725 void SwNoTextFrame::ClearCache()
727 SwFlyFrame
* pFly
= FindFlyFrame();
728 if( pFly
&& pFly
->GetFormat()->GetSurround().IsContour() )
730 ClrContourCache( pFly
->GetVirtDrawObj() );
731 pFly
->NotifyBackground( FindPageFrame(), getFramePrintArea(), PrepareHint::FlyFrameAttributesChanged
);
735 void SwNoTextFrame::OnGraphicArrived()
737 if(GetNode()->GetNodeType() != SwNodeType::Grf
)
743 SwGrfNode
* pNd
= static_cast<SwGrfNode
*>(GetNode());
745 auto pVSh
= pNd
->GetDoc().getIDocumentLayoutAccess().GetCurrentViewShell();
747 pVSh
->OnGraphicArrived(getFrameArea());
750 void SwNoTextFrame::SwClientNotify(const SwModify
& rModify
, const SfxHint
& rHint
)
752 if(rHint
.GetId() == SfxHintId::SwGrfRereadAndInCache
)
754 if(SwNodeType::Grf
!= GetNode()->GetNodeType())
760 else if(rHint
.GetId() == SfxHintId::SwPreGraphicArrived
761 || rHint
.GetId() == SfxHintId::SwGraphicPieceArrived
762 || rHint
.GetId() == SfxHintId::SwLinkedGraphicStreamArrived
)
766 else if (rHint
.GetId() == SfxHintId::SwFormatChange
)
772 else if (rHint
.GetId() == SfxHintId::SwAttrSetChange
)
774 auto pChangeHint
= static_cast<const sw::AttrSetChangeHint
*>(&rHint
);
775 SwContentFrame::SwClientNotify(rModify
, rHint
);
778 for( n
= RES_GRFATR_BEGIN
; n
< RES_GRFATR_END
; ++n
)
779 if( SfxItemState::SET
== pChangeHint
->m_pOld
->GetChgSet()->
780 GetItemState( n
, false ))
784 if(RES_GRFATR_ROTATION
== n
)
786 // RotGrfFlyFrame: Update Handles in view, these may be rotation-dependent
787 // (e.g. crop handles) and need a visualisation update
788 if ( GetNode()->GetNodeType() == SwNodeType::Grf
)
790 SwGrfNode
* pNd
= static_cast<SwGrfNode
*>( GetNode());
791 SwViewShell
*pVSh
= pNd
->GetDoc().getIDocumentLayoutAccess().GetCurrentViewShell();
795 SdrView
* pDrawView
= pVSh
->GetDrawView();
799 pDrawView
->AdjustMarkHdl(nullptr);
803 // RotateFlyFrame3 - invalidate needed for ContentFrame (inner, this)
804 // and LayoutFrame (outer, GetUpper). It is possible to only invalidate
805 // the outer frame, but that leads to an in-between state that gets
806 // potentially painted
809 GetUpper()->InvalidateAll_();
817 if( RES_GRFATR_END
== n
) // not found
823 else if (rHint
.GetId() == SfxHintId::SwObjectDying
)
825 SwContentFrame::SwClientNotify(rModify
, rHint
);
829 else if (rHint
.GetId() == SfxHintId::SwUpdateAttr
)
831 SwContentFrame::SwClientNotify(rModify
, rHint
);
832 if (GetNode()->GetNodeType() == SwNodeType::Grf
)
837 else if (rHint
.GetId() == SfxHintId::SwLegacyModify
)
839 auto pLegacy
= static_cast<const sw::LegacyModifyHint
*>(&rHint
);
840 sal_uInt16 nWhich
= pLegacy
->GetWhich();
842 SwContentFrame::SwClientNotify(rModify
, rHint
);
844 if ( !pLegacy
->m_pNew
|| !isGRFATR(nWhich
) )
852 static void lcl_correctlyAlignRect( SwRect
& rAlignedGrfArea
, const SwRect
& rInArea
, vcl::RenderContext
const * pOut
)
857 tools::Rectangle aPxRect
= pOut
->LogicToPixel( rInArea
.SVRect() );
858 tools::Rectangle
aNewPxRect( aPxRect
);
859 while( aNewPxRect
.Left() < aPxRect
.Left() )
861 rAlignedGrfArea
.AddLeft( 1 );
862 aNewPxRect
= pOut
->LogicToPixel( rAlignedGrfArea
.SVRect() );
864 while( aNewPxRect
.Top() < aPxRect
.Top() )
866 rAlignedGrfArea
.AddTop(+1);
867 aNewPxRect
= pOut
->LogicToPixel( rAlignedGrfArea
.SVRect() );
869 while( aNewPxRect
.Bottom() > aPxRect
.Bottom() )
871 rAlignedGrfArea
.AddBottom( -1 );
872 aNewPxRect
= pOut
->LogicToPixel( rAlignedGrfArea
.SVRect() );
874 while( aNewPxRect
.Right() > aPxRect
.Right() )
876 rAlignedGrfArea
.AddRight(-1);
877 aNewPxRect
= pOut
->LogicToPixel( rAlignedGrfArea
.SVRect() );
881 static bool paintUsingPrimitivesHelper(
882 vcl::RenderContext
& rOutputDevice
,
883 const drawinglayer::primitive2d::Primitive2DContainer
& rSequence
,
884 const basegfx::B2DRange
& rSourceRange
,
885 const basegfx::B2DRange
& rTargetRange
)
887 if(!rSequence
.empty() && !basegfx::fTools::equalZero(rSourceRange
.getWidth()) && !basegfx::fTools::equalZero(rSourceRange
.getHeight()))
889 if(!basegfx::fTools::equalZero(rTargetRange
.getWidth()) && !basegfx::fTools::equalZero(rTargetRange
.getHeight()))
891 // map graphic range to target range. This will e.g. automatically include
892 // the mapping from 1/100th mm content to twips if needed when the target
893 // range is defined in twips
894 const basegfx::B2DHomMatrix
aMappingTransform(
895 basegfx::utils::createSourceRangeTargetRangeTransform(
899 // Fill ViewInformation. Use MappingTransform here, so there is no need to
900 // embed the primitives to it. Use original TargetRange here so there is also
901 // no need to embed the primitives to a MaskPrimitive for cropping. This works
902 // only in this case where the graphic object cannot be rotated, though.
903 drawinglayer::geometry::ViewInformation2D aViewInformation2D
;
904 aViewInformation2D
.setObjectTransformation(aMappingTransform
);
905 aViewInformation2D
.setViewTransformation(rOutputDevice
.GetViewTransformation());
906 aViewInformation2D
.setViewport(rTargetRange
);
908 // get a primitive processor for rendering
909 std::unique_ptr
<drawinglayer::processor2d::BaseProcessor2D
> pProcessor2D(
910 drawinglayer::processor2d::createProcessor2DFromOutputDevice(
911 rOutputDevice
, aViewInformation2D
) );
913 // render and cleanup
914 pProcessor2D
->process(rSequence
);
922 // MM02 original using fallback to VOC and primitive-based version
923 void paintGraphicUsingPrimitivesHelper(
924 vcl::RenderContext
& rOutputDevice
,
925 GraphicObject
const& rGrfObj
,
926 GraphicAttr
const& rGraphicAttr
,
927 const basegfx::B2DHomMatrix
& rGraphicTransform
,
928 const OUString
& rName
,
929 const OUString
& rTitle
,
930 const OUString
& rDescription
)
932 // RotGrfFlyFrame: unify using GraphicPrimitive2D
933 // -> the primitive handles all crop and mirror stuff
934 // -> the primitive renderer will create the needed pdf export data
935 // -> if bitmap content, it will be cached system-dependent
936 drawinglayer::primitive2d::Primitive2DContainer aContent
{
937 new drawinglayer::primitive2d::GraphicPrimitive2D(
942 // MM02 use primitive-based version for visualization
943 paintGraphicUsingPrimitivesHelper(
952 // MM02 new VOC and primitive-based version
953 void paintGraphicUsingPrimitivesHelper(
954 vcl::RenderContext
& rOutputDevice
,
955 drawinglayer::primitive2d::Primitive2DContainer
& rContent
,
956 const basegfx::B2DHomMatrix
& rGraphicTransform
,
957 const OUString
& rName
,
958 const OUString
& rTitle
,
959 const OUString
& rDescription
)
961 // RotateFlyFrame3: If ClipRegion is set at OutputDevice, we
962 // need to use that. Usually the renderer would be a VCL-based
963 // PrimitiveRenderer, but there are system-specific shortcuts that
964 // will *not* use the VCL-Paint of Bitmap and thus ignore this.
965 // Anyways, indirectly using a CLipRegion set at the target OutDev
966 // when using a PrimitiveRenderer is a non-valid implication.
967 // First tried only to use when HasPolyPolygonOrB2DPolyPolygon(),
968 // but there is an optimization at ClipRegion creation that detects
969 // a single Rectangle in a tools::PolyPolygon and forces to a simple
970 // RegionBand-based implementation, so cannot use it here.
971 if(rOutputDevice
.IsClipRegion())
973 basegfx::B2DPolyPolygon
aClip(rOutputDevice
.GetClipRegion().GetAsB2DPolyPolygon());
975 if(0 != aClip
.count())
977 rContent
= drawinglayer::primitive2d::Primitive2DContainer
{
978 new drawinglayer::primitive2d::MaskPrimitive2D(
980 std::move(rContent
)) };
984 if(!rName
.isEmpty() || !rTitle
.isEmpty() || !rDescription
.isEmpty())
986 // Embed to ObjectInfoPrimitive2D when we have Name/Title/Description
987 // information available
988 rContent
= drawinglayer::primitive2d::Primitive2DContainer
{
989 new drawinglayer::primitive2d::ObjectInfoPrimitive2D(
996 basegfx::B2DRange
aTargetRange(0.0, 0.0, 1.0, 1.0);
997 aTargetRange
.transform(rGraphicTransform
);
999 paintUsingPrimitivesHelper(
1006 // DrawContact section
1007 namespace { // anonymous namespace
1008 class ViewObjectContactOfSwNoTextFrame
: public sdr::contact::ViewObjectContact
1011 virtual void createPrimitive2DSequence(
1012 const sdr::contact::DisplayInfo
& rDisplayInfo
,
1013 drawinglayer::primitive2d::Primitive2DDecompositionVisitor
& rVisitor
) const override
;
1015 // tdf#155190 disable this so superclass doesn't wrongly produce NonStruct
1016 virtual bool isExportPDFTags() const override
{ return false; }
1019 ViewObjectContactOfSwNoTextFrame(
1020 sdr::contact::ObjectContact
& rObjectContact
,
1021 sdr::contact::ViewContact
& rViewContact
);
1024 class ViewContactOfSwNoTextFrame
: public sdr::contact::ViewContact
1028 const SwNoTextFrame
& mrSwNoTextFrame
;
1031 // Create an Object-Specific ViewObjectContact, set ViewContact and
1032 // ObjectContact. Always needs to return something.
1033 virtual sdr::contact::ViewObjectContact
& CreateObjectSpecificViewObjectContact(
1034 sdr::contact::ObjectContact
& rObjectContact
) override
;
1037 // read-access to owner
1038 const SwNoTextFrame
& getSwNoTextFrame() const { return mrSwNoTextFrame
; }
1040 // basic constructor, used from SwNoTextFrame.
1041 explicit ViewContactOfSwNoTextFrame(const SwNoTextFrame
& rSwNoTextFrame
);
1044 void ViewObjectContactOfSwNoTextFrame::createPrimitive2DSequence(
1045 const sdr::contact::DisplayInfo
& /*rDisplayInfo*/,
1046 drawinglayer::primitive2d::Primitive2DDecompositionVisitor
& rVisitor
) const
1048 // MM02 get all the parameters formally used in paintGraphicUsingPrimitivesHelper
1049 ViewContactOfSwNoTextFrame
& rVCOfNTF(static_cast<ViewContactOfSwNoTextFrame
&>(GetViewContact()));
1050 const SwNoTextFrame
& rSwNoTextFrame(rVCOfNTF
.getSwNoTextFrame());
1051 SwNoTextNode
& rNoTNd(const_cast<SwNoTextNode
&>(*static_cast<const SwNoTextNode
*>(rSwNoTextFrame
.GetNode())));
1052 SwGrfNode
* pGrfNd(rNoTNd
.GetGrfNode());
1054 if(nullptr != pGrfNd
)
1056 const bool bPrn(GetObjectContact().isOutputToPrinter() || GetObjectContact().isOutputToRecordingMetaFile());
1057 const GraphicObject
& rGrfObj(pGrfNd
->GetGrfObj(bPrn
));
1058 GraphicAttr aGraphicAttr
;
1059 pGrfNd
->GetGraphicAttr(aGraphicAttr
, &rSwNoTextFrame
);
1060 const basegfx::B2DHomMatrix
aGraphicTransform(rSwNoTextFrame
.getFrameAreaTransformation());
1062 // MM02 this is the right place in the VOC-Mechanism to create
1063 // the primitives for visualization - these will be automatically
1064 // buffered and reused
1065 rVisitor
.visit(new drawinglayer::primitive2d::GraphicPrimitive2D(
1072 ViewObjectContactOfSwNoTextFrame::ViewObjectContactOfSwNoTextFrame(
1073 sdr::contact::ObjectContact
& rObjectContact
,
1074 sdr::contact::ViewContact
& rViewContact
)
1075 : sdr::contact::ViewObjectContact(rObjectContact
, rViewContact
)
1079 sdr::contact::ViewObjectContact
& ViewContactOfSwNoTextFrame::CreateObjectSpecificViewObjectContact(
1080 sdr::contact::ObjectContact
& rObjectContact
)
1082 sdr::contact::ViewObjectContact
* pRetval
= new ViewObjectContactOfSwNoTextFrame(rObjectContact
, *this);
1086 ViewContactOfSwNoTextFrame::ViewContactOfSwNoTextFrame(
1087 const SwNoTextFrame
& rSwNoTextFrame
1089 : mrSwNoTextFrame(rSwNoTextFrame
)
1092 } // end of anonymous namespace
1094 sdr::contact::ViewContact
& SwNoTextFrame::GetViewContact() const
1098 const_cast< SwNoTextFrame
* >(this)->mpViewContact
=
1099 std::make_unique
<ViewContactOfSwNoTextFrame
>(*this);
1102 return *mpViewContact
;
1105 /** Paint the graphic.
1107 We require either a QuickDraw-Bitmap or a graphic here. If we do not have
1108 either, we return a replacement.
1110 @todo use aligned rectangle for drawing graphic.
1111 @todo pixel-align coordinations for drawing graphic. */
1112 void SwNoTextFrame::PaintPicture( vcl::RenderContext
* pOut
, const SwRect
&rGrfArea
) const
1114 SwViewShell
* pShell
= getRootFrame()->GetCurrShell();
1116 SwNoTextNode
& rNoTNd
= const_cast<SwNoTextNode
&>(*static_cast<const SwNoTextNode
*>(GetNode()));
1117 SwGrfNode
* pGrfNd
= rNoTNd
.GetGrfNode();
1118 SwOLENode
* pOLENd
= rNoTNd
.GetOLENode();
1120 const bool bPrn
= pOut
== rNoTNd
.getIDocumentDeviceAccess().getPrinter( false ) ||
1121 pOut
->GetConnectMetaFile();
1123 const bool bIsChart
= pOLENd
&& pOLENd
->GetOLEObj().GetObject().IsChart();
1125 // calculate aligned rectangle from parameter <rGrfArea>.
1126 // Use aligned rectangle <aAlignedGrfArea> instead of <rGrfArea> in
1127 // the following code.
1128 SwRect aAlignedGrfArea
= rGrfArea
;
1129 ::SwAlignRect( aAlignedGrfArea
, pShell
, pOut
);
1133 // Because for drawing a graphic left-top-corner and size coordinations are
1134 // used, these coordinations have to be determined on pixel level.
1135 ::SwAlignGrfRect( &aAlignedGrfArea
, *pOut
);
1137 else //if( bIsChart )
1139 // #i78025# charts own borders are not completely visible
1140 // the above pixel correction is not correct - at least not for charts
1141 // so a different pixel correction is chosen here
1142 // this might be a good idea for all other OLE objects also,
1143 // but as I cannot oversee the consequences I fix it only for charts for now
1144 lcl_correctlyAlignRect( aAlignedGrfArea
, rGrfArea
, pOut
);
1149 // Fix for bug fdo#33781
1150 const AntialiasingFlags
nFormerAntialiasingAtOutput( pOut
->GetAntialiasing() );
1151 if (SwDrawView::IsAntiAliasing())
1152 pOut
->SetAntialiasing( nFormerAntialiasingAtOutput
| AntialiasingFlags::Enable
);
1154 ImplPaintPictureGraphic( pOut
, pGrfNd
, bPrn
, aAlignedGrfArea
, pShell
, rNoTNd
);
1156 if ( SwDrawView::IsAntiAliasing() )
1157 pOut
->SetAntialiasing( nFormerAntialiasingAtOutput
);
1159 else // bIsChart || pOLENd
1161 // Fix for bug fdo#33781
1162 const AntialiasingFlags
nFormerAntialiasingAtOutput( pOut
->GetAntialiasing() );
1163 if (SwDrawView::IsAntiAliasing())
1165 AntialiasingFlags nNewAntialiasingAtOutput
= nFormerAntialiasingAtOutput
| AntialiasingFlags::Enable
;
1168 // Adjust AntiAliasing mode at output device for chart OLE
1169 if (pOLENd
&& pOLENd
->IsChart())
1170 nNewAntialiasingAtOutput
|= AntialiasingFlags::PixelSnapHairline
;
1172 pOut
->SetAntialiasing( nNewAntialiasingAtOutput
);
1175 ImplPaintPictureBitmap( pOut
, pOLENd
, bIsChart
, bPrn
, aAlignedGrfArea
, pShell
);
1178 if (SwDrawView::IsAntiAliasing())
1180 pOut
->SetAntialiasing( nFormerAntialiasingAtOutput
);
1185 void SwNoTextFrame::ImplPaintPictureGraphic( vcl::RenderContext
* pOut
,
1186 SwGrfNode
* pGrfNd
, bool bPrn
,
1187 const SwRect
& rAlignedGrfArea
, SwViewShell
* pShell
,
1188 SwNoTextNode
& rNoTNd
) const
1190 bool bContinue
= true;
1191 const GraphicObject
& rGrfObj
= pGrfNd
->GetGrfObj(bPrn
);
1193 GraphicAttr aGrfAttr
;
1194 pGrfNd
->GetGraphicAttr( aGrfAttr
, this );
1199 if ( pGrfNd
->IsLinkedInputStreamReady() )
1201 pGrfNd
->UpdateLinkWithInputStream();
1203 // #i85717#, #i90395# - check, if asynchronous retrieval
1204 // if input stream for the graphic is possible
1205 else if ( ( rGrfObj
.GetType() == GraphicType::Default
||
1206 rGrfObj
.GetType() == GraphicType::NONE
) &&
1207 pGrfNd
->IsLinkedFile() &&
1208 pGrfNd
->IsAsyncRetrieveInputStreamPossible() )
1211 ::sfx2::SvLinkSource
* pGrfObj
= pGrfNd
->GetLink()->GetObj();
1213 !pGrfObj
->IsDataComplete() ||
1214 !(aTmpSz
= pGrfNd
->GetTwipSize()).Width() ||
1217 pGrfNd
->TriggerAsyncRetrieveInputStream(); // #i73788#
1219 OUString
aText( pGrfNd
->GetTitle() );
1220 if ( aText
.isEmpty() )
1221 GetRealURL( *pGrfNd
, aText
);
1222 ::lcl_PaintReplacement( rAlignedGrfArea
, aText
, *pShell
, this, false );
1230 if( !rGrfObj
.GetGraphic().IsSupportedGraphic())
1232 ImplPaintPictureReplacement(rGrfObj
, pGrfNd
, rAlignedGrfArea
, pShell
);
1236 const bool bAnimate
= rGrfObj
.IsAnimated() &&
1237 !pShell
->IsPreview() &&
1238 !pShell
->GetAccessibilityOptions()->IsStopAnimatedGraphics() &&
1239 // #i9684# Stop animation during printing/pdf export
1242 FindFlyFrame() != ::GetFlyFromMarked( nullptr, pShell
))
1244 ImplPaintPictureAnimate(pOut
, pShell
, pGrfNd
, rAlignedGrfArea
);
1248 // MM02 To allow system-dependent buffering of the involved
1249 // bitmaps it is necessary to re-use the involved primitives
1250 // and their already executed decomposition (also for
1251 // performance reasons). This is usually done in DrawingLayer
1252 // by using the VOC-Mechanism (see descriptions elsewhere).
1253 // To get that here, make the involved SwNoTextFrame (this)
1254 // a sdr::contact::ViewContact supplier by supporting
1255 // a GetViewContact() - call. For ObjectContact we can use
1256 // the already existing ObjectContact from the involved
1257 // DrawingLayer. For this, the helper classes
1258 // ViewObjectContactOfSwNoTextFrame
1259 // ViewContactOfSwNoTextFrame
1260 // are created which support the VOC-mechanism in its minimal
1261 // form. This allows automatic and view-dependent (multiple edit
1262 // windows, print, etc.) re-use of the created primitives.
1263 // Also: Will be very useful when completely changing the Writer
1264 // repaint to VOC and Primitives, too.
1265 static const char* pDisableMM02Goodies(getenv("SAL_DISABLE_MM02_GOODIES"));
1266 static bool bUseViewObjectContactMechanism(nullptr == pDisableMM02Goodies
);
1267 // tdf#130951 for safety reasons use fallback if ViewObjectContactMechanism
1268 // fails for some reason - usually could only be not to find the correct
1270 bool bSucceeded(false);
1272 if(bUseViewObjectContactMechanism
)
1274 // MM02 use VOC-mechanism and buffer primitives
1275 SwViewShellImp
* pImp(pShell
->Imp());
1276 SdrPageView
* pPageView(nullptr != pImp
1277 ? pImp
->GetPageView()
1279 // tdf#130951 caution - target may be Window, use the correct OutputDevice
1280 OutputDevice
* pTarget((pShell
->isOutputToWindow() && pShell
->GetWin())
1281 ? pShell
->GetWin()->GetOutDev()
1282 : pShell
->GetOut());
1283 SdrPageWindow
* pPageWindow(nullptr != pPageView
&& nullptr != pTarget
1284 ? pPageView
->FindPageWindow(*pTarget
)
1287 if(nullptr != pPageWindow
)
1289 sdr::contact::ObjectContact
& rOC(pPageWindow
->GetObjectContact());
1290 sdr::contact::ViewContact
& rVC(GetViewContact());
1291 sdr::contact::ViewObjectContact
& rVOC(rVC
.GetViewObjectContact(rOC
));
1292 sdr::contact::DisplayInfo aDisplayInfo
;
1294 drawinglayer::primitive2d::Primitive2DContainer
aPrimitives(rVOC
.getPrimitive2DSequence(aDisplayInfo
));
1295 const basegfx::B2DHomMatrix
aGraphicTransform(getFrameAreaTransformation());
1297 paintGraphicUsingPrimitivesHelper(
1301 nullptr == pGrfNd
->GetFlyFormat() ? OUString() : pGrfNd
->GetFlyFormat()->GetName(),
1303 rNoTNd
.GetDescription());
1310 // MM02 fallback to direct paint with primitive-recreation
1311 // which will block reusage of system-dependent bitmap data
1312 const basegfx::B2DHomMatrix
aGraphicTransform(getFrameAreaTransformation());
1314 paintGraphicUsingPrimitivesHelper(
1319 nullptr == pGrfNd
->GetFlyFormat() ? OUString() : pGrfNd
->GetFlyFormat()->GetName(),
1321 rNoTNd
.GetDescription());
1325 void SwNoTextFrame::ImplPaintPictureAnimate(vcl::RenderContext
* pOut
, SwViewShell
* pShell
,
1326 SwGrfNode
* pGrfNd
, const SwRect
& rAlignedGrfArea
) const
1328 OutputDevice
* pVout
;
1329 if( pOut
== pShell
->GetOut() && SwRootFrame::FlushVout() )
1332 pOut
= pShell
->GetOut();
1334 else if( pShell
->GetWin() && pOut
->IsVirtual() )
1337 pOut
= pShell
->GetWin()->GetOutDev();
1342 OSL_ENSURE( !pOut
->IsVirtual() ||
1343 pShell
->GetViewOptions()->IsPDFExport() || pShell
->isOutputToWindow(),
1344 "pOut should not be a virtual device" );
1346 pGrfNd
->StartGraphicAnimation(pOut
, rAlignedGrfArea
.Pos(),
1347 rAlignedGrfArea
.SSize(), reinterpret_cast<sal_IntPtr
>(this),
1351 void SwNoTextFrame::ImplPaintPictureReplacement(const GraphicObject
& rGrfObj
, SwGrfNode
* pGrfNd
,
1352 const SwRect
& rAlignedGrfArea
, SwViewShell
* pShell
) const
1356 if( GraphicType::NONE
== rGrfObj
.GetType() )
1357 pResId
= STR_COMCORE_READERROR
;
1358 else if ( !rGrfObj
.GetGraphic().IsSupportedGraphic() )
1359 pResId
= STR_COMCORE_CANT_SHOW
;
1363 (aText
= pGrfNd
->GetTitle()).isEmpty() &&
1364 (!GetRealURL( *pGrfNd
, aText
) || aText
.isEmpty()))
1366 pResId
= STR_COMCORE_READERROR
;
1369 aText
= SwResId(pResId
);
1371 ::lcl_PaintReplacement( rAlignedGrfArea
, aText
, *pShell
, this, true );
1374 void SwNoTextFrame::ImplPaintPictureBitmap( vcl::RenderContext
* pOut
,
1375 SwOLENode
* pOLENd
, bool bIsChart
, bool bPrn
, const SwRect
& rAlignedGrfArea
,
1376 SwViewShell
* pShell
) const
1382 basegfx::B2DRange aSourceRange
;
1383 const drawinglayer::primitive2d::Primitive2DContainer
aSequence(
1384 pOLENd
->GetOLEObj().tryToGetChartContentAsPrimitive2DSequence(
1388 if(!aSequence
.empty() && !aSourceRange
.isEmpty())
1390 const basegfx::B2DRange
aTargetRange(
1391 rAlignedGrfArea
.Left(), rAlignedGrfArea
.Top(),
1392 rAlignedGrfArea
.Right(), rAlignedGrfArea
.Bottom());
1394 Color aOldBackColor
;
1395 SvxDrawPage
* pDrawPage
= pOLENd
->GetOLEObj().tryToGetChartDrawPage();
1396 SdrPage
* pPage
= pDrawPage
? pDrawPage
->GetSdrPage() : nullptr;
1399 SdrModel
& rModel
= pPage
->getSdrModelFromSdrPage();
1400 SdrOutliner
& rOutl
= rModel
.GetDrawOutliner();
1401 aOldBackColor
= rOutl
.GetBackgroundColor();
1402 rOutl
.SetBackgroundColor(pPage
->GetPageBackgroundColor());
1405 bDone
= paintUsingPrimitivesHelper(
1412 pPage
->getSdrModelFromSdrPage().GetDrawOutliner().SetBackgroundColor(aOldBackColor
);
1416 if(bDone
|| !pOLENd
)
1419 // SwOLENode does not have a known GraphicObject, need to
1420 // work with Graphic instead
1421 const Graphic
* pGraphic
= pOLENd
->GetGraphic();
1422 const Point
aPosition(rAlignedGrfArea
.Pos());
1423 const Size
aSize(rAlignedGrfArea
.SSize());
1425 uno::Reference
<embed::XEmbeddedObject
> xObj
= pOLENd
->GetOLEObj().GetOleRef();
1427 if ( pGraphic
&& pGraphic
->GetType() != GraphicType::NONE
)
1429 pGraphic
->Draw(*pOut
, aPosition
, aSize
);
1431 // shade the representation if the object is activated outplace
1432 if ( xObj
.is() && xObj
->getCurrentState() == embed::EmbedStates::ACTIVE
)
1435 ::svt::EmbeddedObjectRef::DrawShading(
1444 ::svt::EmbeddedObjectRef::DrawPaintReplacement(
1445 tools::Rectangle(aPosition
, aSize
),
1446 pOLENd
->GetOLEObj().GetCurrentPersistName(),
1450 sal_Int64 nMiscStatus
= xObj
? xObj
->getStatus(pOLENd
->GetAspect()) : 0;
1451 if ( !bPrn
&& dynamic_cast< const SwCursorShell
*>( pShell
) != nullptr &&
1452 (nMiscStatus
& embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE
))
1454 const SwFlyFrame
*pFly
= FindFlyFrame();
1455 assert( pFly
!= nullptr );
1456 static_cast<SwFEShell
*>(pShell
)->ConnectObj( pOLENd
->GetOLEObj().GetObject(), pFly
->getFramePrintArea(), pFly
->getFrameArea());
1460 bool SwNoTextFrame::IsTransparent() const
1462 const SwViewShell
* pSh
= getRootFrame()->GetCurrShell();
1464 if ( !pSh
|| !pSh
->GetViewOptions()->IsGraphic() )
1469 const SwGrfNode
*pNd
;
1471 if( nullptr != (pNd
= GetNode()->GetGrfNode()) )
1473 if(pNd
->IsTransparent())
1479 // RotateFlyFrame3: If we are transformed, there are 'free' areas between
1480 // the Graphic and the Border/Padding stuff - at least as long as those
1481 // (Border and Padding) are not transformed, too
1482 if(isTransformableSwFrame())
1484 // we can be more specific - rotations of multiples of
1485 // 90 degrees will leave no gaps. Go from [0.0 .. 2PI]
1486 // to [0 .. 360] and check modulo 90
1487 const tools::Long
nRot(static_cast<tools::Long
>(basegfx::rad2deg(getLocalFrameRotation())));
1488 const bool bMultipleOf90(0 == (nRot
% 90));
1496 //#29381# OLE are always transparent
1497 if(nullptr != GetNode()->GetOLENode())
1502 // return false by default to avoid background paint
1506 void SwNoTextFrame::StopAnimation( const OutputDevice
* pOut
) const
1508 // Stop animated graphics
1509 const SwGrfNode
* pGrfNd
= GetNode()->GetGrfNode();
1511 if( pGrfNd
&& pGrfNd
->IsAnimated() )
1513 const_cast< SwGrfNode
* >(pGrfNd
)->StopGraphicAnimation( pOut
, reinterpret_cast<sal_IntPtr
>(this) );
1517 bool SwNoTextFrame::HasAnimation() const
1519 const SwGrfNode
* pGrfNd
= GetNode()->GetGrfNode();
1520 return pGrfNd
&& pGrfNd
->IsAnimated();
1523 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */