1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#pragma once
#include <editeng/txtrange.hxx>
#include <swtypes.hxx>
#include <swrect.hxx>
#include <com/sun/star/text/WrapTextMode.hpp>
#include <nodeoffset.hxx>
#include <memory>
#include <vector>
class OutputDevice;
class SwPageFrame;
class SdrObject;
class SwFormat;
class SwAnchoredObject;
class SwTextFrame;
class SwDrawTextInfo;
class SwContourCache;
class SwBreakPortion;
class SwTextFormatInfo;
typedef std::vector< SwAnchoredObject* > SwAnchoredObjList;
/** Contour-cache global variable, initialized/destroyed in txtinit.cxx
and needed in txtfly.cxx by text wrapping.
*/
extern SwContourCache *pContourCache;
#define POLY_CNT 20
#define POLY_MIN 5
#define POLY_MAX 4000
void ClrContourCache( const SdrObject *pObj );
class SwContourCache
{
friend void ClrContourCache();
struct CacheItem
{
const SdrObject *mpSdrObj;
std::unique_ptr<TextRanger> mxTextRanger;
};
std::vector<CacheItem> mvItems;
tools::Long mnPointCount;
SwRect ContourRect( const SwFormat* pFormat, const SdrObject* pObj,
const SwTextFrame* pFrame, const SwRect &rLine, const tools::Long nXPos,
const bool bRight );
public:
SwContourCache();
~SwContourCache();
const SdrObject* GetObject( sal_uInt16 nPos ) const{ return mvItems[ nPos ].mpSdrObj; }
sal_uInt16 GetCount() const { return mvItems.size(); }
void ClrObject( sal_uInt16 nPos );
/**
Computes the rectangle that will cover the object in the given line.
For _non_ contour-flow objects, this is simply the overlap area of
BoundRect (including spacing), and the line, for contour-flow,
the tools::PolyPolygon of the object gets traversed
*/
static SwRect CalcBoundRect( const SwAnchoredObject* pAnchoredObj,
const SwRect &rLine,
const SwTextFrame* pFrame,
const tools::Long nXPos,
const bool bRight );
};
// MS Word wraps on sides with even less space (value guessed).
#define TEXT_MIN_SMALL 300
/**
The purpose of this class is to be the universal interface between
formatting/text output and the possibly overlapping free-flying frames.
During formatting the formatter gets the information from SwTextFly, whether
a certain area is present by the attributes of an overlapping frame.
Such areas are represented by dummy portions.
The whole text output and touch-up is, again, forwarded to a SwTextFly.
This one decides, whether parts of the text need to be clipped and splits
the areas for e.g. a DrawRect.
Please note that all free-flying frames are located in a PtrArray, sorted
by TopLeft.
Internally we always use document-global values. The IN and OUT parameters
are, however, adjusted to the needs of the LineIter most of the time. That
is: they are converted to frame- and window-local coordinates.
If multiple frames with wrap attributes are located on the same line, we get
the following settings for the text flow:
L/R P L R N
P -P-P- -P-L -P R- -P N
L -L P- -L L -L R- -L N
R R-P- R-L R R- R N
N N P- N L N R- N N
(P=parallel, L=left, R=right, N=no wrap)
We can describe the behaviour as follows:
Every frame can push away text, with the restriction that it only has influence
until the next frame.
*/
class SwTextFly
{
const SwPageFrame * m_pPage;
const SwAnchoredObject * mpCurrAnchoredObj;
const SwTextFrame * m_pCurrFrame;
const SwTextFrame * m_pMaster;
std::unique_ptr<SwAnchoredObjList> mpAnchoredObjList;
tools::Long m_nMinBottom;
tools::Long m_nNextTop; /// Stores the upper edge of the "next" frame
SwNodeOffset m_nCurrFrameNodeIndex;
bool m_bOn : 1;
bool m_bTopRule: 1;
bool mbIgnoreCurrentFrame: 1;
bool mbIgnoreContour: 1;
/** boolean, indicating if objects in page header|footer are considered for
text frames not in page header|footer.
*/
bool mbIgnoreObjsInHeaderFooter: 1;
/**
This method will be called during the LineIter formatting
\li to compute the position of the next \c FlyPortion
\li remember new overlappings after a change of the line height.
\param[in] rPortion
Scope: document global.
*/
SwRect GetFrame_( const SwRect &rPortion ) const;
SwAnchoredObjList& InitAnchoredObjList();
public:
SwAnchoredObjList& GetAnchoredObjList() const;
private:
/**
Look for the first object which overlaps with the rectangle.
Iterates over the anchored object list mpAnchoredObjList.
*/
bool ForEach( const SwRect &rRect, SwRect* pRect, bool bAvoid ) const;
/**
\li There is less than 2cm space on both sides for the text:
no surround (css::text::WrapTextMode_NONE)
\li There is more than 2cm space on only one side:
surround on that side (css::text::WrapTextMode_LEFT or css::text::WrapTextMode_RIGHT)
\li There is more than 2cm space on both sides, the object is
larger than 1.5cm: surround on the wider side
(css::text::WrapTextMode_LEFT or css::text::WrapTextMode_RIGHT)
\li There is more than 2cm space on both sides and the object
width is less than 1.5cm: both sides surround (css::text::WrapTextMode_PARALLEL)
*/
css::text::WrapTextMode GetSurroundForTextWrap( const SwAnchoredObject* pAnchoredObj ) const;
/**
The right margin is the right margin or it is determined by the
next object standing on the line.
*/
void CalcRightMargin( SwRect &rFly,
SwAnchoredObjList::size_type nPos,
const SwRect &rLine ) const;
/**
The left margin is the left margin of the current PrintArea or
it is determined by the last FlyFrame, which stands on the line.
*/
void CalcLeftMargin( SwRect &rFly,
SwAnchoredObjList::size_type nPos,
const SwRect &rLine ) const;
/**
\return the position in sorted array
*/
SwAnchoredObjList::size_type GetPos( const SwAnchoredObject* pAnchoredObj ) const;
bool GetTop( const SwAnchoredObject* _pAnchoredObj,
const bool bInFootnote,
const bool bInFooterOrHeader );
SwTwips CalcMinBottom() const;
const SwTextFrame* GetMaster_();
public:
SwTextFly();
SwTextFly( const SwTextFrame *pFrame );
SwTextFly( const SwTextFly& rTextFly );
~SwTextFly();
void CtorInitTextFly( const SwTextFrame *pFrame );
void SetTopRule();
SwRect GetFrame( const SwRect &rPortion ) const;
bool IsOn() const;
/**
If there is no flying object frame standing in rRect (usually the current row),
then we are turning ourself off.
\param rRect is global to the document!
*/
bool Relax( const SwRect &rRect );
bool Relax();
SwTwips GetMinBottom() const;
/// Gets the maximum of the fly frame bottoms.
SwTwips GetMaxBottom(const SwBreakPortion& rPortion, const SwTextFormatInfo& rInfo) const;
const SwTextFrame* GetMaster() const;
// This temporary variable needs to be manipulated in const methods
tools::Long GetNextTop() const;
void SetNextTop( tools::Long nNew ) const;
/**
Determines the demanded rectangle for an anchored object,
considering its surround for text wrapping.
\param pAnchoredObj the object for which to get the bounds
\param rLine the bounds of the line to format
\return the flying object bounds
*/
SwRect AnchoredObjToRect( const SwAnchoredObject* pAnchoredObj,
const SwRect& rRect ) const;
/**
This method is called by DrawText().
Ensures that the overlapping frames (except the transparent frames) won't
be scribbled by setting clip regions so that only the portions that are not
in the area of FlyFrames that are opaque and above the current frame will
be output.
DrawText() takes over the on optimization!
*/
void DrawTextOpaque( SwDrawTextInfo &rInf );
/**
Two subtleties needs to be mentioned:
\li DrawRect() is allowed over the ClipRects
\li FlyToRect() returns bigger values than the frame data
Ensure that the overlapping frames (except the transparent frames)
won't be scribbled
*/
void DrawFlyRect( OutputDevice* pOut, const SwRect &rRect );
/**
Used to switch off the SwTextFly when there is no overlapping object (Relax).
\param[in] the line area
\return whether the line will be overlapped by a frame
*/
bool IsAnyFrame( const SwRect &rLine ) const;
/**
Same as IsAnyFrame(const SwRect&), but uses the current frame print
area
*/
bool IsAnyFrame() const;
/**
true when a frame or DrawObj must be taken in account. The optimizations
like Paint/FormatEmpty for empty sentences or the virtual OutputDevice can
be used only when false is returned.
\param rRect
The rectangle can be empty, the current frame is then used. The value is
global to the document.
*/
bool IsAnyObj( const SwRect& rRect ) const;
void SetIgnoreCurrentFrame( bool bNew );
void SetIgnoreContour( bool bNew );
void SetIgnoreObjsInHeaderFooter( const bool bNew );
SwRect GetFrameArea() const;
};
inline SwAnchoredObjList& SwTextFly::GetAnchoredObjList() const
{
return mpAnchoredObjList
? *mpAnchoredObjList
: const_cast<SwTextFly*>(this)->InitAnchoredObjList();
}
inline void SwTextFly::SetTopRule()
{
m_bTopRule = false;
}
inline bool SwTextFly::IsOn() const
{
return m_bOn;
}
inline bool SwTextFly::Relax( const SwRect &rRect )
{
if (m_bOn)
{
m_bOn = IsAnyFrame( rRect );
}
return m_bOn;
}
inline bool SwTextFly::Relax()
{
if (m_bOn)
{
m_bOn = IsAnyFrame();
}
return m_bOn;
}
inline SwTwips SwTextFly::GetMinBottom() const
{
return mpAnchoredObjList ? m_nMinBottom : CalcMinBottom();
}
inline const SwTextFrame* SwTextFly::GetMaster() const
{
return m_pMaster ? m_pMaster : const_cast<SwTextFly*>(this)->GetMaster_();
}
inline tools::Long SwTextFly::GetNextTop() const
{
return m_nNextTop;
}
inline void SwTextFly::SetNextTop( tools::Long nNew ) const
{
const_cast<SwTextFly*>(this)->m_nNextTop = nNew;
}
inline SwRect SwTextFly::GetFrame( const SwRect &rRect ) const
{
return m_bOn ? GetFrame_( rRect ) : SwRect();
}
inline void SwTextFly::SetIgnoreCurrentFrame( bool bNew )
{
mbIgnoreCurrentFrame = bNew;
}
inline void SwTextFly::SetIgnoreContour( bool bNew )
{
mbIgnoreContour = bNew;
}
inline void SwTextFly::SetIgnoreObjsInHeaderFooter( const bool bNew )
{
mbIgnoreObjsInHeaderFooter = bNew;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|