related: tdf#162601 UNIQUE function is case-insensitive also for non ASCII
[LibreOffice.git] / sw / source / core / inc / txtfly.hxx
blob9047e127e7d8c18238e25515744d026f7022e2d1
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 #pragma once
22 #include <editeng/txtrange.hxx>
23 #include <swtypes.hxx>
24 #include <swrect.hxx>
25 #include <com/sun/star/text/WrapTextMode.hpp>
26 #include <nodeoffset.hxx>
27 #include <memory>
28 #include <vector>
30 class OutputDevice;
31 class SwPageFrame;
32 class SdrObject;
33 class SwFormat;
34 class SwAnchoredObject;
35 class SwTextFrame;
36 class SwDrawTextInfo;
37 class SwContourCache;
38 class SwBreakPortion;
39 class SwTextFormatInfo;
41 typedef std::vector< SwAnchoredObject* > SwAnchoredObjList;
43 /** Contour-cache global variable, initialized/destroyed in txtinit.cxx
44 and needed in txtfly.cxx by text wrapping.
46 extern SwContourCache *pContourCache;
48 #define POLY_CNT 20
49 #define POLY_MIN 5
50 #define POLY_MAX 4000
52 void ClrContourCache( const SdrObject *pObj );
54 class SwContourCache
56 friend void ClrContourCache();
57 struct CacheItem
59 const SdrObject *mpSdrObj;
60 std::unique_ptr<TextRanger> mxTextRanger;
62 std::vector<CacheItem> mvItems;
63 tools::Long mnPointCount;
64 SwRect ContourRect( const SwFormat* pFormat, const SdrObject* pObj,
65 const SwTextFrame* pFrame, const SwRect &rLine, const tools::Long nXPos,
66 const bool bRight );
68 public:
69 SwContourCache();
70 ~SwContourCache();
71 const SdrObject* GetObject( sal_uInt16 nPos ) const{ return mvItems[ nPos ].mpSdrObj; }
72 sal_uInt16 GetCount() const { return mvItems.size(); }
73 void ClrObject( sal_uInt16 nPos );
75 /**
76 Computes the rectangle that will cover the object in the given line.
78 For _non_ contour-flow objects, this is simply the overlap area of
79 BoundRect (including spacing), and the line, for contour-flow,
80 the tools::PolyPolygon of the object gets traversed
82 static SwRect CalcBoundRect( const SwAnchoredObject* pAnchoredObj,
83 const SwRect &rLine,
84 const SwTextFrame* pFrame,
85 const tools::Long nXPos,
86 const bool bRight );
89 // MS Word wraps on sides with even less space (value guessed).
90 #define TEXT_MIN_SMALL 300
92 /**
93 The purpose of this class is to be the universal interface between
94 formatting/text output and the possibly overlapping free-flying frames.
95 During formatting the formatter gets the information from SwTextFly, whether
96 a certain area is present by the attributes of an overlapping frame.
97 Such areas are represented by dummy portions.
99 The whole text output and touch-up is, again, forwarded to a SwTextFly.
100 This one decides, whether parts of the text need to be clipped and splits
101 the areas for e.g. a DrawRect.
103 Please note that all free-flying frames are located in a PtrArray, sorted
104 by TopLeft.
106 Internally we always use document-global values. The IN and OUT parameters
107 are, however, adjusted to the needs of the LineIter most of the time. That
108 is: they are converted to frame- and window-local coordinates.
109 If multiple frames with wrap attributes are located on the same line, we get
110 the following settings for the text flow:
112 L/R P L R N
113 P -P-P- -P-L -P R- -P N
114 L -L P- -L L -L R- -L N
115 R R-P- R-L R R- R N
116 N N P- N L N R- N N
118 (P=parallel, L=left, R=right, N=no wrap)
120 We can describe the behaviour as follows:
121 Every frame can push away text, with the restriction that it only has influence
122 until the next frame.
124 class SwTextFly
126 const SwPageFrame * m_pPage;
127 const SwAnchoredObject * mpCurrAnchoredObj;
128 const SwTextFrame * m_pCurrFrame;
129 const SwTextFrame * m_pMaster;
130 std::unique_ptr<SwAnchoredObjList> mpAnchoredObjList;
132 tools::Long m_nMinBottom;
133 tools::Long m_nNextTop; /// Stores the upper edge of the "next" frame
134 SwNodeOffset m_nCurrFrameNodeIndex;
136 bool m_bOn : 1;
137 bool m_bTopRule: 1;
138 bool mbIgnoreCurrentFrame: 1;
139 bool mbIgnoreContour: 1;
141 /** boolean, indicating if objects in page header|footer are considered for
142 text frames not in page header|footer.
144 bool mbIgnoreObjsInHeaderFooter: 1;
147 This method will be called during the LineIter formatting
148 \li to compute the position of the next \c FlyPortion
149 \li remember new overlappings after a change of the line height.
151 \param[in] rPortion
152 Scope: document global.
154 SwRect GetFrame_( const SwRect &rPortion ) const;
156 SwAnchoredObjList& InitAnchoredObjList();
158 public:
159 SwAnchoredObjList& GetAnchoredObjList() const;
160 private:
163 Look for the first object which overlaps with the rectangle.
164 Iterates over the anchored object list mpAnchoredObjList.
166 bool ForEach( const SwRect &rRect, SwRect* pRect, bool bAvoid ) const;
169 \li There is less than 2cm space on both sides for the text:
170 no surround (css::text::WrapTextMode_NONE)
172 \li There is more than 2cm space on only one side:
173 surround on that side (css::text::WrapTextMode_LEFT or css::text::WrapTextMode_RIGHT)
175 \li There is more than 2cm space on both sides, the object is
176 larger than 1.5cm: surround on the wider side
177 (css::text::WrapTextMode_LEFT or css::text::WrapTextMode_RIGHT)
179 \li There is more than 2cm space on both sides and the object
180 width is less than 1.5cm: both sides surround (css::text::WrapTextMode_PARALLEL)
182 css::text::WrapTextMode GetSurroundForTextWrap( const SwAnchoredObject* pAnchoredObj ) const;
185 The right margin is the right margin or it is determined by the
186 next object standing on the line.
188 void CalcRightMargin( SwRect &rFly,
189 SwAnchoredObjList::size_type nPos,
190 const SwRect &rLine ) const;
193 The left margin is the left margin of the current PrintArea or
194 it is determined by the last FlyFrame, which stands on the line.
196 void CalcLeftMargin( SwRect &rFly,
197 SwAnchoredObjList::size_type nPos,
198 const SwRect &rLine ) const;
201 \return the position in sorted array
203 SwAnchoredObjList::size_type GetPos( const SwAnchoredObject* pAnchoredObj ) const;
205 bool GetTop( const SwAnchoredObject* _pAnchoredObj,
206 const bool bInFootnote,
207 const bool bInFooterOrHeader );
209 SwTwips CalcMinBottom() const;
211 const SwTextFrame* GetMaster_();
213 public:
215 SwTextFly();
216 SwTextFly( const SwTextFrame *pFrame );
217 SwTextFly( const SwTextFly& rTextFly );
218 ~SwTextFly();
220 void CtorInitTextFly( const SwTextFrame *pFrame );
222 void SetTopRule();
224 SwRect GetFrame( const SwRect &rPortion ) const;
225 bool IsOn() const;
228 If there is no flying object frame standing in rRect (usually the current row),
229 then we are turning ourself off.
231 \param rRect is global to the document!
233 bool Relax( const SwRect &rRect );
234 bool Relax();
236 SwTwips GetMinBottom() const;
238 /// Gets the maximum of the fly frame bottoms.
239 SwTwips GetMaxBottom(const SwBreakPortion& rPortion, const SwTextFormatInfo& rInfo) const;
241 const SwTextFrame* GetMaster() const;
243 // This temporary variable needs to be manipulated in const methods
244 tools::Long GetNextTop() const;
245 void SetNextTop( tools::Long nNew ) const;
248 Determines the demanded rectangle for an anchored object,
249 considering its surround for text wrapping.
251 \param pAnchoredObj the object for which to get the bounds
252 \param rLine the bounds of the line to format
254 \return the flying object bounds
256 SwRect AnchoredObjToRect( const SwAnchoredObject* pAnchoredObj,
257 const SwRect& rRect ) const;
260 This method is called by DrawText().
262 Ensures that the overlapping frames (except the transparent frames) won't
263 be scribbled by setting clip regions so that only the portions that are not
264 in the area of FlyFrames that are opaque and above the current frame will
265 be output.
267 DrawText() takes over the on optimization!
269 void DrawTextOpaque( SwDrawTextInfo &rInf );
272 Two subtleties needs to be mentioned:
273 \li DrawRect() is allowed over the ClipRects
274 \li FlyToRect() returns bigger values than the frame data
276 Ensure that the overlapping frames (except the transparent frames)
277 won't be scribbled
279 void DrawFlyRect( OutputDevice* pOut, const SwRect &rRect );
282 Used to switch off the SwTextFly when there is no overlapping object (Relax).
284 \param[in] the line area
285 \return whether the line will be overlapped by a frame
287 bool IsAnyFrame( const SwRect &rLine ) const;
290 Same as IsAnyFrame(const SwRect&), but uses the current frame print
291 area
293 bool IsAnyFrame() const;
296 true when a frame or DrawObj must be taken in account. The optimizations
297 like Paint/FormatEmpty for empty sentences or the virtual OutputDevice can
298 be used only when false is returned.
300 \param rRect
301 The rectangle can be empty, the current frame is then used. The value is
302 global to the document.
304 bool IsAnyObj( const SwRect& rRect ) const;
306 void SetIgnoreCurrentFrame( bool bNew );
307 void SetIgnoreContour( bool bNew );
309 void SetIgnoreObjsInHeaderFooter( const bool bNew );
311 SwRect GetFrameArea() const;
314 inline SwAnchoredObjList& SwTextFly::GetAnchoredObjList() const
316 return mpAnchoredObjList
317 ? *mpAnchoredObjList
318 : const_cast<SwTextFly*>(this)->InitAnchoredObjList();
321 inline void SwTextFly::SetTopRule()
323 m_bTopRule = false;
326 inline bool SwTextFly::IsOn() const
328 return m_bOn;
331 inline bool SwTextFly::Relax( const SwRect &rRect )
333 if (m_bOn)
335 m_bOn = IsAnyFrame( rRect );
337 return m_bOn;
340 inline bool SwTextFly::Relax()
342 if (m_bOn)
344 m_bOn = IsAnyFrame();
346 return m_bOn;
349 inline SwTwips SwTextFly::GetMinBottom() const
351 return mpAnchoredObjList ? m_nMinBottom : CalcMinBottom();
354 inline const SwTextFrame* SwTextFly::GetMaster() const
356 return m_pMaster ? m_pMaster : const_cast<SwTextFly*>(this)->GetMaster_();
359 inline tools::Long SwTextFly::GetNextTop() const
361 return m_nNextTop;
364 inline void SwTextFly::SetNextTop( tools::Long nNew ) const
366 const_cast<SwTextFly*>(this)->m_nNextTop = nNew;
369 inline SwRect SwTextFly::GetFrame( const SwRect &rRect ) const
371 return m_bOn ? GetFrame_( rRect ) : SwRect();
374 inline void SwTextFly::SetIgnoreCurrentFrame( bool bNew )
376 mbIgnoreCurrentFrame = bNew;
379 inline void SwTextFly::SetIgnoreContour( bool bNew )
381 mbIgnoreContour = bNew;
384 inline void SwTextFly::SetIgnoreObjsInHeaderFooter( const bool bNew )
386 mbIgnoreObjsInHeaderFooter = bNew;
389 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */