summaryrefslogtreecommitdiff
path: root/sw/source/core/text/txtfly.hxx
blob: 2dd2d7f2e7717bba25235dbaefc48f82bbf2e299 (plain)
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
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef _TXTFLY_HXX
#define _TXTFLY_HXX

#include "swtypes.hxx"
#include "swrect.hxx"

class OutputDevice;
class SwCntntFrm;
class SwPageFrm;
class SwTxtFly;
class SdrObject;
class SwTxtPaintInfo;
class SwFmt;
class TextRanger;
class SwAnchoredObject;

#include <fmtsrndenum.hxx>

#include <vector>
typedef std::vector< SwAnchoredObject* > SwAnchoredObjList;

enum PAGESIDE { LEFT_SIDE, RIGHT_SIDE, DONTKNOW_SIDE };


class SwDrawTextInfo;
class SwContourCache;
/** Contour-cache global variable, initialized/destroyed in txtinit.cxx
    and needed in txtfly.cxx by text wrapping.
  */
extern SwContourCache *pContourCache;
class SwTxtFrm;

#define POLY_CNT 20
#define POLY_MIN 5
#define POLY_MAX 4000

class SwContourCache
{
    friend void ClrContourCache();
    const SdrObject *pSdrObj[ POLY_CNT ];
    TextRanger *pTextRanger[ POLY_CNT ];
    long nPntCnt;
    MSHORT nObjCnt;
    const SwRect ContourRect( const SwFmt* pFmt, const SdrObject* pObj,
        const SwTxtFrm* pFrm, const SwRect &rLine, const long nXPos,
        const sal_Bool bRight );

public:
    SwContourCache();
    ~SwContourCache();
    const SdrObject* GetObject( MSHORT nPos ) const{ return pSdrObj[ nPos ]; }
    MSHORT GetCount() const { return nObjCnt; }
    void ClrObject( MSHORT 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 PolyPolygon of the object gets traversed
     */
    static const SwRect CalcBoundRect( const SwAnchoredObject* pAnchoredObj,
                                       const SwRect &rLine,
                                       const SwTxtFrm* pFrm,
                                       const long nXPos,
                                       const sal_Bool bRight );
};

/**
   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 SwTxtFly, 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 SwTxtFly.
   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 SwTxtFly
{
    const SwPageFrm             * pPage;
    const SwAnchoredObject      * mpCurrAnchoredObj;
    const SwTxtFrm              * pCurrFrm;
    const SwCntntFrm            * pMaster;
    SwAnchoredObjList           * mpAnchoredObjList;

    long nMinBottom;
    long nNextTop;  /// Stores the upper edge of the "next" frame
    sal_uLong nIndex;

    sal_Bool bOn : 1;
    sal_Bool bLeftSide : 1;
    sal_Bool bTopRule: 1;
    sal_Bool mbIgnoreCurrentFrame: 1;
    sal_Bool mbIgnoreContour: 1;

    /** boolean, indicating if objects in page header|footer are considered for
        text frames not in page header|footer.
     */
    sal_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 _GetFrm( const SwRect &rPortion, sal_Bool bTop ) const;

    SwAnchoredObjList* InitAnchoredObjList();

    SwAnchoredObjList* GetAnchoredObjList() const;

    /**
        Look for the first object which overlaps with the rectangle.
        Iterates over the anchored object list mpAnchoredObjList.
    */
    sal_Bool ForEach( const SwRect &rRect, SwRect* pRect, sal_Bool bAvoid ) const;

    /**
      \li There is less than 2cm space on both sides for the text:
      no surround (SURROUND_NONE)

      \li There is more than 2cm space on only one side:
      surround on that side (SURROUND_LEFT or SURROUND_RIGHT)

      \li There is more than 2cm space on both sides, the object is
      larger than 1.5cm: surround on the wider side
      (SURROUND_LET or SURROUND_RIGHT)

      \li There is more than 2cm space on both sides and the object
      width is less than 1.5cm: both sides surround (SURROUND_PARALLEL)
     */
    SwSurround _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 FlyFrm, 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;

    sal_Bool GetTop( const SwAnchoredObject* _pAnchoredObj,
                     const sal_Bool bInFtn,
                     const sal_Bool bInFooterOrHeader );

    SwTwips CalcMinBottom() const;

    const SwCntntFrm* _GetMaster();

public:

    SwTxtFly();
    SwTxtFly( const SwTxtFrm *pFrm );
    SwTxtFly( const SwTxtFly& rTxtFly );
    ~SwTxtFly();

    void CtorInitTxtFly( const SwTxtFrm *pFrm );

    void SetTopRule();

    SwRect GetFrm( const SwRect &rPortion, sal_Bool bTop = sal_True ) const;
    sal_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!
     */
    sal_Bool Relax( const SwRect &rRect );
    sal_Bool Relax();

    SwTwips GetMinBottom() const;
    const SwCntntFrm* GetMaster() const;

    // This temporary variable needs to be manipulated in const methods
    long GetNextTop() const;
    void SetNextTop( 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 FlyFrms that are opaque and above the current frame will
        be output.

        DrawText() takes over the on optimization!
     */
    sal_Bool 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,
                      const SwTxtPaintInfo &rInf, sal_Bool bNoGraphic = sal_False );

    /**
        Used to switch off the SwTxtFly when there is no overlapping object (Relax).

        \param[in] the line area
        \return whether the line will be overlapped by a frame
     */
    sal_Bool IsAnyFrm( const SwRect &rLine ) const;

    /**
        Same as IsAnyFrm(const SwRect&), but uses the current frame print
        area
     */
    sal_Bool IsAnyFrm() const;

    /**
        sal_True when a frame or DrawObj must to be taken in account. The optimizations
        like Paint/FormatEmpty for empty sentences or the the virtual OutputDevice can
        be used only when sal_False is returned.

        \param rRect
            The rectangle can be empty, the current frame is then used. The value is
            global to the document.
      */
    sal_Bool IsAnyObj( const SwRect& rRect ) const;

    void SetIgnoreCurrentFrame( sal_Bool bNew );
    void SetIgnoreContour( sal_Bool bNew );

    void SetIgnoreObjsInHeaderFooter( const sal_Bool _bNew );
};


inline SwAnchoredObjList* SwTxtFly::GetAnchoredObjList() const
{
    return mpAnchoredObjList
           ? mpAnchoredObjList
           : const_cast<SwTxtFly*>(this)->InitAnchoredObjList();
}

inline void SwTxtFly::SetTopRule()
{
    bTopRule = sal_False;
}

inline sal_Bool SwTxtFly::IsOn() const
{
    return bOn;
}

inline sal_Bool SwTxtFly::Relax( const SwRect &rRect )
{
    return 0 != (bOn = bOn && IsAnyFrm( rRect ));
}

inline sal_Bool SwTxtFly::Relax()
{
    return 0 != (bOn = bOn && IsAnyFrm());
}

inline SwTwips SwTxtFly::GetMinBottom() const
{
    return mpAnchoredObjList ? nMinBottom : CalcMinBottom();
}

inline const SwCntntFrm* SwTxtFly::GetMaster() const
{
    return pMaster ? pMaster : ((SwTxtFly*)this)->_GetMaster();
}

inline long SwTxtFly::GetNextTop() const
{
    return nNextTop;
}

inline void SwTxtFly::SetNextTop( long nNew ) const
{
    ((SwTxtFly*)this)->nNextTop = nNew;
}

inline SwRect SwTxtFly::GetFrm( const SwRect &rRect, sal_Bool bTop ) const
{
    return bOn ? _GetFrm( rRect, bTop ) : SwRect();
}

inline void SwTxtFly::SetIgnoreCurrentFrame( sal_Bool bNew )
{
    mbIgnoreCurrentFrame = bNew;
}

inline void SwTxtFly::SetIgnoreContour( sal_Bool bNew )
{
    mbIgnoreContour = bNew;
}

inline void SwTxtFly::SetIgnoreObjsInHeaderFooter( const sal_Bool _bNew )
{
    mbIgnoreObjsInHeaderFooter = _bNew;
}

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */