android: Update app-specific/MIME type icons
[LibreOffice.git] / sw / source / core / text / porfly.cxx
blob7bee98d9821aa8e3921b1409261976199a344b85
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <dcontact.hxx>
21 #include <dflyobj.hxx>
22 #include <pam.hxx>
23 #include "portab.hxx"
24 #include <flyfrm.hxx>
25 #include <rootfrm.hxx>
26 #include <frmfmt.hxx>
27 #include <viewsh.hxx>
28 #include <textboxhelper.hxx>
29 #include <IDocumentState.hxx>
31 #include <sal/log.hxx>
32 #include <fmtanchr.hxx>
33 #include <fmtflcnt.hxx>
34 #include <flyfrms.hxx>
35 #include <txatbase.hxx>
36 #include "porfly.hxx"
37 #include "porlay.hxx"
38 #include "inftxt.hxx"
40 #include <sortedobjs.hxx>
41 #include <officecfg/Office/Common.hxx>
42 #include <PostItMgr.hxx>
44 /**
45 * class SwFlyPortion => we expect a frame-locale SwRect!
48 void SwFlyPortion::Paint( const SwTextPaintInfo& ) const
52 bool SwFlyPortion::Format( SwTextFormatInfo &rInf )
54 OSL_ENSURE( GetFix() >= rInf.X(), "SwFlyPortion::Format" );
56 // tabs must be expanded
57 if( rInf.GetLastTab() )
58 rInf.GetLastTab()->FormatEOL( rInf );
60 rInf.GetLast()->FormatEOL( rInf );
61 PrtWidth( o3tl::narrowing<sal_uInt16>(GetFix() - rInf.X() + PrtWidth()) );
62 if( !Width() )
64 OSL_ENSURE( Width(), "+SwFlyPortion::Format: a fly is a fly is a fly" );
65 Width(1);
68 // resetting
69 rInf.SetFly( nullptr );
70 rInf.Width( rInf.RealWidth() );
71 rInf.GetParaPortion()->SetFly();
73 // trailing blank:
74 if( rInf.GetIdx() < TextFrameIndex(rInf.GetText().getLength())
75 && TextFrameIndex(1) < rInf.GetIdx()
76 && !rInf.GetRest()
77 && ' ' == rInf.GetChar( rInf.GetIdx() )
78 && ' ' != rInf.GetChar(rInf.GetIdx() - TextFrameIndex(1))
79 && ( !rInf.GetLast() || !rInf.GetLast()->IsBreakPortion() ) )
81 SetBlankWidth( rInf.GetTextSize(OUString(' ')).Width() );
82 SetLen(TextFrameIndex(1));
85 const sal_uInt16 nNewWidth = o3tl::narrowing<sal_uInt16>(rInf.X() + PrtWidth());
86 if( rInf.Width() <= nNewWidth )
88 Truncate();
89 if( nNewWidth > rInf.Width() )
91 PrtWidth( nNewWidth - rInf.Width() );
92 SetFixWidth( PrtWidth() );
94 return true;
96 return false;
99 bool SwFlyCntPortion::Format( SwTextFormatInfo &rInf )
101 bool bFull = rInf.Width() < rInf.X() + PrtWidth();
103 if( bFull )
105 // If the line is full, and the character-bound frame is at
106 // the beginning of a line
107 // If it is not possible to side step into a Fly
108 // "Begin of line" criteria ( ! rInf.X() ) has to be extended.
109 // KerningPortions at beginning of line, e.g., for grid layout
110 // must be considered.
111 const SwLinePortion* pLastPor = rInf.GetLast();
112 const auto nLeft = ( pLastPor &&
113 ( pLastPor->IsKernPortion() ||
114 pLastPor->IsErgoSumPortion() ) ) ?
115 pLastPor->Width() :
118 if( nLeft == rInf.X() && ! rInf.GetFly() )
120 Width( rInf.Width() );
121 bFull = false; // so that notes can still be placed in this line
123 else
125 if( !rInf.GetFly() )
126 rInf.SetNewLine( true );
127 Width(0);
128 SetAscent(0);
129 SetLen(TextFrameIndex(0));
130 if( rInf.GetLast() )
131 rInf.GetLast()->FormatEOL( rInf );
133 return bFull;
137 rInf.GetParaPortion()->SetFly();
138 return bFull;
141 //TODO: improve documentation
142 /** move character-bound objects inside the given area
144 * This allows moving those objects from Master to Follow, or vice versa.
146 * @param pNew
147 * @param nStart
148 * @param nEnd
150 void SwTextFrame::MoveFlyInCnt(SwTextFrame *pNew,
151 TextFrameIndex const nStart, TextFrameIndex const nEnd)
153 SwSortedObjs *pObjs = GetDrawObjs();
154 if ( nullptr == pObjs )
155 return;
157 for ( size_t i = 0; GetDrawObjs() && i < pObjs->size(); ++i )
159 // Consider changed type of <SwSortedList> entries
160 SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
161 const SwFormatAnchor& rAnch = pAnchoredObj->GetFrameFormat().GetAnchor();
162 if (rAnch.GetAnchorId() == RndStdIds::FLY_AS_CHAR)
164 const SwPosition* pPos = rAnch.GetContentAnchor();
165 TextFrameIndex const nIndex(MapModelToViewPos(*pPos));
166 if (nStart <= nIndex && nIndex < nEnd)
168 if ( auto pFlyFrame = pAnchoredObj->DynCastFlyFrame() )
170 RemoveFly( pFlyFrame );
171 pNew->AppendFly( pFlyFrame );
173 else if ( dynamic_cast< const SwAnchoredDrawObject *>( pAnchoredObj ) != nullptr )
175 RemoveDrawObj( *pAnchoredObj );
176 pNew->AppendDrawObj( *pAnchoredObj );
178 --i;
184 TextFrameIndex SwTextFrame::CalcFlyPos( SwFrameFormat const * pSearch )
186 sw::MergedAttrIter iter(*this);
187 for (SwTextAttr const* pHt = iter.NextAttr(); pHt; pHt = iter.NextAttr())
189 if( RES_TXTATR_FLYCNT == pHt->Which() )
191 SwFrameFormat* pFrameFormat = pHt->GetFlyCnt().GetFrameFormat();
192 if( pFrameFormat == pSearch )
194 return TextFrameIndex(pHt->GetStart());
198 OSL_ENSURE(false, "CalcFlyPos: Not Found!");
199 return TextFrameIndex(COMPLETE_STRING);
202 void sw::FlyContentPortion::Paint(const SwTextPaintInfo& rInf) const
204 // Baseline output
205 // Re-paint everything at a CompletePaint call
206 SwRect aRepaintRect(rInf.GetPaintRect());
208 if(rInf.GetTextFrame()->IsRightToLeft())
209 rInf.GetTextFrame()->SwitchLTRtoRTL(aRepaintRect);
211 if(rInf.GetTextFrame()->IsVertical())
212 rInf.GetTextFrame()->SwitchHorizontalToVertical(aRepaintRect);
214 if(!((m_pFly->IsCompletePaint() ||
215 m_pFly->getFrameArea().Overlaps(aRepaintRect)) &&
216 SwFlyFrame::IsPaint(m_pFly->GetVirtDrawObj(), m_pFly->getRootFrame()->GetCurrShell())))
217 return;
219 SwRect aRect(m_pFly->getFrameArea());
220 if(!m_pFly->IsCompletePaint())
221 aRect.Intersection_(aRepaintRect);
223 // GetFlyFrame() may change the layout mode at the output device.
225 SwLayoutModeModifier aLayoutModeModifier(*rInf.GetOut());
226 m_pFly->PaintSwFrame(const_cast<vcl::RenderContext&>(*rInf.GetOut()), aRect);
228 // track changes: cross out the image, if it is deleted
229 const SwFrame *pFrame = m_pFly->Lower();
230 if ( GetAuthor() != std::string::npos && IsDeleted() && pFrame )
232 SwRect aPaintRect( pFrame->GetPaintArea() );
234 const AntialiasingFlags nFormerAntialiasing( rInf.GetOut()->GetAntialiasing() );
235 const bool bIsAntiAliasing = officecfg::Office::Common::Drawinglayer::AntiAliasing::get();
236 if ( bIsAntiAliasing )
237 const_cast<vcl::RenderContext&>(*rInf.GetOut()).SetAntialiasing(AntialiasingFlags::Enable);
238 tools::Long startX = aPaintRect.Left( ), endX = aPaintRect.Right();
239 tools::Long startY = aPaintRect.Top( ), endY = aPaintRect.Bottom();
240 const_cast<vcl::RenderContext&>(*rInf.GetOut()).SetLineColor(
241 SwPostItMgr::GetColorAnchor(GetAuthor()) );
242 const_cast<vcl::RenderContext&>(*rInf.GetOut()).DrawLine(Point(startX, startY), Point(endX, endY));
243 const_cast<vcl::RenderContext&>(*rInf.GetOut()).DrawLine(Point(startX, endY), Point(endX, startY));
244 if ( bIsAntiAliasing )
245 const_cast<vcl::RenderContext&>(*rInf.GetOut()).SetAntialiasing(nFormerAntialiasing);
248 const_cast<SwTextPaintInfo&>(rInf).GetRefDev()->SetLayoutMode(rInf.GetOut()->GetLayoutMode());
250 // As the OutputDevice might be anything, the font must be re-selected.
251 // Being in const method should not be a problem.
252 const_cast<SwTextPaintInfo&>(rInf).SelectFont();
254 assert(rInf.GetVsh());
255 SAL_WARN_IF(rInf.GetVsh()->GetOut() != rInf.GetOut(), "sw.core", "SwFlyCntPortion::Paint: Outdev has changed");
256 if(rInf.GetVsh())
257 const_cast<SwTextPaintInfo&>(rInf).SetOut(rInf.GetVsh()->GetOut());
260 void sw::DrawFlyCntPortion::Paint(const SwTextPaintInfo&) const
262 if(!m_pContact->GetAnchorFrame())
264 // No direct positioning of the drawing object is needed
265 m_pContact->ConnectToLayout();
270 * Use the dimensions of pFly->OutRect()
272 SwFlyCntPortion::SwFlyCntPortion()
273 : m_bMax(false)
274 , m_bDeleted(false)
275 , m_nAuthor(std::string::npos)
276 , m_eAlign(sw::LineAlign::NONE)
278 mnLineLength = TextFrameIndex(1);
279 SetWhichPor(PortionType::FlyCnt);
282 sw::FlyContentPortion::FlyContentPortion(SwFlyInContentFrame* pFly)
283 : m_pFly(pFly)
285 SAL_WARN_IF(!pFly, "sw.core", "SwFlyCntPortion::SwFlyCntPortion: no SwFlyInContentFrame!");
288 sw::DrawFlyCntPortion::DrawFlyCntPortion(SwFrameFormat const & rFormat)
289 : m_pContact(nullptr)
291 rFormat.CallSwClientNotify(sw::CreatePortionHint(&m_pContact));
292 assert(m_pContact);
295 sw::FlyContentPortion* sw::FlyContentPortion::Create(const SwTextFrame& rFrame, SwFlyInContentFrame* pFly, const Point& rBase, tools::Long nLnAscent, tools::Long nLnDescent, tools::Long nFlyAsc, tools::Long nFlyDesc, AsCharFlags nFlags)
297 auto pNew(new sw::FlyContentPortion(pFly));
298 pNew->SetBase(rFrame, rBase, nLnAscent, nLnDescent, nFlyAsc, nFlyDesc, nFlags | AsCharFlags::UlSpace | AsCharFlags::Init);
299 return pNew;
302 sw::DrawFlyCntPortion* sw::DrawFlyCntPortion::Create(const SwTextFrame& rFrame, SwFrameFormat const & rFormat, const Point& rBase, tools::Long nLnAscent, tools::Long nLnDescent, tools::Long nFlyAsc, tools::Long nFlyDesc, AsCharFlags nFlags)
304 auto pNew(new DrawFlyCntPortion(rFormat));
305 pNew->SetBase(rFrame, rBase, nLnAscent, nLnDescent, nFlyAsc, nFlyDesc, nFlags | AsCharFlags::UlSpace | AsCharFlags::Init);
306 return pNew;
309 sw::DrawFlyCntPortion::~DrawFlyCntPortion() {};
310 sw::FlyContentPortion::~FlyContentPortion() {};
312 SdrObject* sw::FlyContentPortion::GetSdrObj(const SwTextFrame&)
314 return m_pFly->GetVirtDrawObj();
317 SdrObject* sw::DrawFlyCntPortion::GetSdrObj(const SwTextFrame& rFrame)
319 SdrObject* pSdrObj;
320 // Determine drawing object ('master' or 'virtual') by frame
321 pSdrObj = m_pContact->GetDrawObjectByAnchorFrame(rFrame);
322 if(!pSdrObj)
324 SAL_WARN("sw.core", "SwFlyCntPortion::SetBase(..) - No drawing object found by <GetDrawContact()->GetDrawObjectByAnchorFrame( rFrame )>");
325 pSdrObj = m_pContact->GetMaster();
328 // Call <SwAnchoredDrawObject::MakeObjPos()> to assure that flag at
329 // the <DrawFrameFormat> and at the <SwAnchoredDrawObject> instance are
330 // correctly set
331 if(pSdrObj)
332 m_pContact->GetAnchoredObj(pSdrObj)->MakeObjPos();
333 return pSdrObj;
337 * After setting the RefPoints, the ascent needs to be recalculated
338 * because it is dependent on RelPos
340 * @param rBase CAUTION: needs to be an absolute value!
342 void SwFlyCntPortion::SetBase( const SwTextFrame& rFrame, const Point &rBase,
343 tools::Long nLnAscent, tools::Long nLnDescent,
344 tools::Long nFlyAsc, tools::Long nFlyDesc,
345 AsCharFlags nFlags )
347 // Use new class to position object
348 // Determine drawing object
349 SdrObject* pSdrObj = GetSdrObj(rFrame);
350 if (!pSdrObj)
351 return;
353 // position object
354 objectpositioning::SwAsCharAnchoredObjectPosition aObjPositioning(
355 *pSdrObj,
356 rBase, nFlags,
357 nLnAscent, nLnDescent, nFlyAsc, nFlyDesc );
359 // Scope of local variable <aObjPosInProgress>
361 SwObjPositioningInProgress aObjPosInProgress( *pSdrObj );
362 aObjPositioning.CalcPosition();
365 if (auto pFormat = FindFrameFormat(pSdrObj))
367 if (pFormat->GetOtherTextBoxFormats()
368 && pFormat->GetAnchor().GetAnchorId() == RndStdIds::FLY_AS_CHAR)
370 // TODO: Improve security with moving this sync call to other place,
371 // where it works for typing but not during layout calc.
372 const bool bModified = pFormat->GetDoc()->getIDocumentState().IsEnableSetModified();
373 pFormat->GetDoc()->getIDocumentState().SetEnableSetModified(false);
374 SwTextBoxHelper::synchronizeGroupTextBoxProperty(SwTextBoxHelper::changeAnchor, pFormat,
375 pFormat->FindRealSdrObject());
376 SwTextBoxHelper::synchronizeGroupTextBoxProperty(SwTextBoxHelper::syncTextBoxSize,
377 pFormat, pFormat->FindRealSdrObject());
378 pFormat->GetDoc()->getIDocumentState().SetEnableSetModified(bModified);
382 SetAlign( aObjPositioning.GetLineAlignment() );
384 m_aRef = aObjPositioning.GetAnchorPos();
385 if( nFlags & AsCharFlags::Rotate )
386 SvXSize( aObjPositioning.GetObjBoundRectInclSpacing().SSize() );
387 else
388 SvLSize( aObjPositioning.GetObjBoundRectInclSpacing().SSize() );
389 if( Height() )
391 // GetRelPosY returns the relative position to baseline (if 0, the
392 // upper border of the FlyCnt if on the baseline of a line)
393 SwTwips nRelPos = aObjPositioning.GetRelPosY();
394 if ( nRelPos < 0 )
396 mnAscent = -nRelPos;
397 if( mnAscent > Height() )
398 Height( mnAscent );
400 else
402 mnAscent = 0;
403 Height( Height() + o3tl::narrowing<sal_uInt16>(nRelPos) );
406 else
408 Height( 1 );
409 mnAscent = 0;
413 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */