Coverage Report

Created: 2025-07-07 10:01

/src/libreoffice/vcl/source/control/imivctl2.cxx
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
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/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
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 .
18
 */
19
20
#include "imivctl.hxx"
21
#include <sal/log.hxx>
22
23
IcnCursor_Impl::IcnCursor_Impl( SvxIconChoiceCtrl_Impl* pOwner )
24
0
{
25
0
    pView       = pOwner;
26
0
    pCurEntry   = nullptr;
27
0
    nDeltaWidth = 0;
28
0
    nDeltaHeight= 0;
29
0
    nCols       = 0;
30
0
    nRows       = 0;
31
0
}
32
33
IcnCursor_Impl::~IcnCursor_Impl()
34
0
{
35
0
}
36
37
sal_uInt16 IcnCursor_Impl::GetSortListPos( SvxIconChoiceCtrlEntryPtrVec& rList, tools::Long nValue,
38
    bool bVertical )
39
0
{
40
0
    sal_uInt16 nCount = rList.size();
41
0
    if( !nCount )
42
0
        return 0;
43
44
0
    sal_uInt16 nCurPos = 0;
45
0
    tools::Long nPrevValue = LONG_MIN;
46
0
    while( nCount )
47
0
    {
48
0
        const tools::Rectangle& rRect = pView->GetEntryBoundRect( rList[nCurPos] );
49
0
        tools::Long nCurValue;
50
0
        if( bVertical )
51
0
            nCurValue = rRect.Top();
52
0
        else
53
0
            nCurValue = rRect.Left();
54
0
        if( nValue >= nPrevValue && nValue <= nCurValue )
55
0
            return nCurPos;
56
0
        nPrevValue = nCurValue;
57
0
        nCount--;
58
0
        nCurPos++;
59
0
    }
60
0
    return rList.size();
61
0
}
62
63
void IcnCursor_Impl::ImplCreate()
64
0
{
65
0
    pView->CheckBoundingRects();
66
0
    DBG_ASSERT(xColumns==nullptr&&xRows==nullptr,"ImplCreate: Not cleared");
67
68
0
    SetDeltas();
69
70
0
    xColumns.reset(new IconChoiceMap);
71
0
    xRows.reset(new IconChoiceMap);
72
73
0
    size_t nCount = pView->maEntries.size();
74
0
    for( size_t nCur = 0; nCur < nCount; nCur++ )
75
0
    {
76
0
        SvxIconChoiceCtrlEntry* pEntry = pView->maEntries[ nCur ].get();
77
        // const Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
78
0
        tools::Rectangle rRect( pView->CalcBmpRect( pEntry ) );
79
0
        short nY = static_cast<short>( ((rRect.Top()+rRect.Bottom())/2) / nDeltaHeight );
80
0
        short nX = static_cast<short>( ((rRect.Left()+rRect.Right())/2) / nDeltaWidth );
81
82
        // capture rounding errors
83
0
        if( nY >= nRows )
84
0
            nY = sal::static_int_cast< short >(nRows - 1);
85
0
        if( nX >= nCols )
86
0
            nX = sal::static_int_cast< short >(nCols - 1);
87
88
0
        SvxIconChoiceCtrlEntryPtrVec& rColEntry = (*xColumns)[nX];
89
0
        sal_uInt16 nIns = GetSortListPos( rColEntry, rRect.Top(), true );
90
0
        rColEntry.insert( rColEntry.begin() + nIns, pEntry );
91
92
0
        SvxIconChoiceCtrlEntryPtrVec& rRowEntry = (*xRows)[nY];
93
0
        nIns = GetSortListPos( rRowEntry, rRect.Left(), false );
94
0
        rRowEntry.insert( rRowEntry.begin() + nIns, pEntry );
95
96
0
        pEntry->nX = nX;
97
0
        pEntry->nY = nY;
98
0
    }
99
0
}
100
101
102
void IcnCursor_Impl::Clear()
103
0
{
104
0
    if( xColumns )
105
0
    {
106
0
        xColumns.reset();
107
0
        xRows.reset();
108
0
        pCurEntry = nullptr;
109
0
        nDeltaWidth = 0;
110
0
        nDeltaHeight = 0;
111
0
    }
112
0
}
113
114
SvxIconChoiceCtrlEntry* IcnCursor_Impl::SearchCol(sal_uInt16 nCol, sal_uInt16 nTop, sal_uInt16 nBottom,
115
    bool bDown, bool bSimple )
116
0
{
117
0
    DBG_ASSERT(pCurEntry, "SearchCol: No reference entry");
118
0
    IconChoiceMap::iterator mapIt = xColumns->find( nCol );
119
0
    if ( mapIt == xColumns->end() )
120
0
        return nullptr;
121
0
    SvxIconChoiceCtrlEntryPtrVec const & rList = mapIt->second;
122
0
    const sal_uInt16 nCount = rList.size();
123
0
    if( !nCount )
124
0
        return nullptr;
125
126
0
    const tools::Rectangle& rRefRect = pView->GetEntryBoundRect(pCurEntry);
127
128
0
    if( bSimple )
129
0
    {
130
0
        SvxIconChoiceCtrlEntryPtrVec::const_iterator it = std::find( rList.begin(), rList.end(), pCurEntry );
131
132
0
        assert(it != rList.end()); //Entry not in Col-List
133
0
        if (it == rList.end())
134
0
            return nullptr;
135
136
0
        if( bDown )
137
0
        {
138
0
            while( ++it != rList.end() )
139
0
            {
140
0
                SvxIconChoiceCtrlEntry* pEntry = *it;
141
0
                const tools::Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
142
0
                if( rRect.Top() > rRefRect.Top() )
143
0
                    return pEntry;
144
0
            }
145
0
            return nullptr;
146
0
        }
147
0
        else
148
0
        {
149
0
            SvxIconChoiceCtrlEntryPtrVec::const_reverse_iterator it2(it);
150
0
            while (it2 != rList.rend())
151
0
            {
152
0
                SvxIconChoiceCtrlEntry* pEntry = *it2;
153
0
                const tools::Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
154
0
                if( rRect.Top() < rRefRect.Top() )
155
0
                    return pEntry;
156
0
                ++it2;
157
0
            }
158
0
            return nullptr;
159
0
        }
160
0
    }
161
162
0
    if( nTop > nBottom )
163
0
        std::swap(nTop, nBottom);
164
165
0
    tools::Long nMinDistance = LONG_MAX;
166
0
    SvxIconChoiceCtrlEntry* pResult = nullptr;
167
0
    for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
168
0
    {
169
0
        SvxIconChoiceCtrlEntry* pEntry = rList[ nCur ];
170
0
        if( pEntry != pCurEntry )
171
0
        {
172
0
            sal_uInt16 nY = pEntry->nY;
173
0
            if( nY >= nTop && nY <= nBottom )
174
0
            {
175
0
                const tools::Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
176
0
                tools::Long nDistance = rRect.Top() - rRefRect.Top();
177
0
                if( nDistance < 0 )
178
0
                    nDistance *= -1;
179
0
                if( nDistance && nDistance < nMinDistance )
180
0
                {
181
0
                    nMinDistance = nDistance;
182
0
                    pResult = pEntry;
183
0
                }
184
0
            }
185
0
        }
186
0
    }
187
0
    return pResult;
188
0
}
189
190
SvxIconChoiceCtrlEntry* IcnCursor_Impl::SearchRow(sal_uInt16 nRow, sal_uInt16 nLeft, sal_uInt16 nRight,
191
    bool bRight, bool bSimple )
192
0
{
193
0
    DBG_ASSERT(pCurEntry,"SearchRow: No reference entry");
194
0
    IconChoiceMap::iterator mapIt = xRows->find( nRow );
195
0
    if ( mapIt == xRows->end() )
196
0
        return nullptr;
197
0
    SvxIconChoiceCtrlEntryPtrVec const & rList = mapIt->second;
198
0
    const sal_uInt16 nCount = rList.size();
199
0
    if( !nCount )
200
0
        return nullptr;
201
202
0
    const tools::Rectangle& rRefRect = pView->GetEntryBoundRect(pCurEntry);
203
204
0
    if( bSimple )
205
0
    {
206
0
        SvxIconChoiceCtrlEntryPtrVec::const_iterator it = std::find( rList.begin(), rList.end(), pCurEntry );
207
208
0
        assert(it != rList.end()); //Entry not in Row-List
209
0
        if (it == rList.end())
210
0
            return nullptr;
211
212
0
        if( bRight )
213
0
        {
214
0
            while( ++it != rList.end() )
215
0
            {
216
0
                SvxIconChoiceCtrlEntry* pEntry = *it;
217
0
                const tools::Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
218
0
                if( rRect.Left() > rRefRect.Left() )
219
0
                    return pEntry;
220
0
            }
221
0
            return nullptr;
222
0
        }
223
0
        else
224
0
        {
225
0
            SvxIconChoiceCtrlEntryPtrVec::const_reverse_iterator it2(it);
226
0
            while (it2 != rList.rend())
227
0
            {
228
0
                SvxIconChoiceCtrlEntry* pEntry = *it2;
229
0
                const tools::Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
230
0
                if( rRect.Left() < rRefRect.Left() )
231
0
                    return pEntry;
232
0
                ++it2;
233
0
            }
234
0
            return nullptr;
235
0
        }
236
237
0
    }
238
0
    if( nRight < nLeft )
239
0
        std::swap(nRight, nLeft);
240
241
0
    tools::Long nMinDistance = LONG_MAX;
242
0
    SvxIconChoiceCtrlEntry* pResult = nullptr;
243
0
    for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
244
0
    {
245
0
        SvxIconChoiceCtrlEntry* pEntry = rList[ nCur ];
246
0
        if( pEntry != pCurEntry )
247
0
        {
248
0
            sal_uInt16 nX = pEntry->nX;
249
0
            if( nX >= nLeft && nX <= nRight )
250
0
            {
251
0
                const tools::Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
252
0
                tools::Long nDistance = rRect.Left() - rRefRect.Left();
253
0
                if( nDistance < 0 )
254
0
                    nDistance *= -1;
255
0
                if( nDistance && nDistance < nMinDistance )
256
0
                {
257
0
                    nMinDistance = nDistance;
258
0
                    pResult = pEntry;
259
0
                }
260
0
            }
261
0
        }
262
0
    }
263
0
    return pResult;
264
0
}
265
266
267
/*
268
    Searches, starting from the passed value, the next entry to the left/to the
269
    right. Example for bRight = sal_True:
270
271
                  c
272
                b c
273
              a b c
274
            S 1 1 1      ====> search direction
275
              a b c
276
                b c
277
                  c
278
279
    S : starting position
280
    1 : first searched rectangle
281
    a,b,c : 2nd, 3rd, 4th searched rectangle
282
*/
283
284
SvxIconChoiceCtrlEntry* IcnCursor_Impl::GoLeftRight( SvxIconChoiceCtrlEntry* pCtrlEntry, bool bRight )
285
0
{
286
0
    SvxIconChoiceCtrlEntry* pResult;
287
0
    pCurEntry = pCtrlEntry;
288
0
    Create();
289
0
    sal_uInt16 nY = pCtrlEntry->nY;
290
0
    sal_uInt16 nX = pCtrlEntry->nX;
291
0
    DBG_ASSERT(nY< nRows,"GoLeftRight:Bad column");
292
0
    DBG_ASSERT(nX< nCols,"GoLeftRight:Bad row");
293
    // neighbor in same row?
294
0
    if( bRight )
295
0
        pResult = SearchRow(
296
0
            nY, nX, sal::static_int_cast< sal_uInt16 >(nCols-1), true, true );
297
0
    else
298
0
        pResult = SearchRow( nY, 0, nX, false, true );
299
0
    if( pResult )
300
0
        return pResult;
301
302
0
    tools::Long nCurCol = nX;
303
304
0
    tools::Long nColOffs, nLastCol;
305
0
    if( bRight )
306
0
    {
307
0
        nColOffs = 1;
308
0
        nLastCol = nCols;
309
0
    }
310
0
    else
311
0
    {
312
0
        nColOffs = -1;
313
0
        nLastCol = -1;   // 0-1
314
0
    }
315
316
0
    sal_uInt16 nRowMin = nY;
317
0
    sal_uInt16 nRowMax = nY;
318
0
    do
319
0
    {
320
0
        SvxIconChoiceCtrlEntry* pEntry = SearchCol(static_cast<sal_uInt16>(nCurCol), nRowMin, nRowMax, true, false);
321
0
        if( pEntry )
322
0
            return pEntry;
323
0
        if( nRowMin )
324
0
            nRowMin--;
325
0
        if( nRowMax < (nRows-1))
326
0
            nRowMax++;
327
0
        nCurCol += nColOffs;
328
0
    } while( nCurCol != nLastCol );
329
0
    return nullptr;
330
0
}
331
332
SvxIconChoiceCtrlEntry* IcnCursor_Impl::GoPageUpDown( const SvxIconChoiceCtrlEntry* pStart, bool bDown)
333
0
{
334
0
    const tools::Long nPos = static_cast<tools::Long>(pView->GetEntryListPos( pStart ));
335
0
    tools::Long nEntriesInView = pView->aOutputSize.Height() / pView->nGridDY;
336
0
    nEntriesInView *=
337
0
        ((pView->aOutputSize.Width()+(pView->nGridDX/2)) / pView->nGridDX );
338
0
    tools::Long nNewPos = nPos;
339
0
    if( bDown )
340
0
    {
341
0
        nNewPos += nEntriesInView;
342
0
        if( nNewPos >= static_cast<tools::Long>(pView->maEntries.size()) )
343
0
            nNewPos = pView->maEntries.size() - 1;
344
0
    }
345
0
    else
346
0
    {
347
0
        nNewPos -= nEntriesInView;
348
0
        if( nNewPos < 0 )
349
0
            nNewPos = 0;
350
0
    }
351
0
    if( nPos != nNewPos )
352
0
        return pView->maEntries[ static_cast<size_t>(nNewPos) ].get();
353
0
    return nullptr;
354
0
}
355
356
SvxIconChoiceCtrlEntry* IcnCursor_Impl::GoUpDown( const SvxIconChoiceCtrlEntry* pCtrlEntry, bool bDown)
357
0
{
358
0
    sal_uLong nPos = pView->GetEntryListPos( pCtrlEntry );
359
0
    if( bDown && nPos < (pView->maEntries.size() - 1) )
360
0
        return pView->maEntries[ nPos + 1 ].get();
361
0
    else if( !bDown && nPos > 0 )
362
0
        return pView->maEntries[ nPos - 1 ].get();
363
0
    return nullptr;
364
0
}
365
366
void IcnCursor_Impl::SetDeltas()
367
0
{
368
0
    const Size& rSize = pView->aVirtOutputSize;
369
0
    nCols = rSize.Width() / pView->nGridDX;
370
0
    if( !nCols )
371
0
        nCols = 1;
372
0
    nRows = rSize.Height() / pView->nGridDY;
373
0
    if( (nRows * pView->nGridDY) < rSize.Height() )
374
0
        nRows++;
375
0
    if( !nRows )
376
0
        nRows = 1;
377
378
0
    nDeltaWidth = static_cast<short>(rSize.Width() / nCols);
379
0
    nDeltaHeight = static_cast<short>(rSize.Height() / nRows);
380
0
    if( !nDeltaHeight )
381
0
    {
382
0
        nDeltaHeight = 1;
383
0
        SAL_INFO("vcl", "SetDeltas:Bad height");
384
0
    }
385
0
    if( !nDeltaWidth )
386
0
    {
387
0
        nDeltaWidth = 1;
388
0
        SAL_INFO("vcl", "SetDeltas:Bad width");
389
0
    }
390
0
}
391
392
IcnGridMap_Impl::IcnGridMap_Impl(SvxIconChoiceCtrl_Impl* pView)
393
0
 : _pView(pView), _nGridCols(0), _nGridRows(0)
394
0
{
395
0
}
396
397
IcnGridMap_Impl::~IcnGridMap_Impl()
398
0
{
399
0
}
400
401
void IcnGridMap_Impl::Expand()
402
0
{
403
0
    if( !_pGridMap )
404
0
        Create_Impl();
405
0
    else
406
0
    {
407
0
        sal_uInt16 nNewGridRows = _nGridRows;
408
0
        sal_uInt16 nNewGridCols = _nGridCols;
409
0
        nNewGridCols += 50;
410
411
0
        size_t nNewCellCount = static_cast<size_t>(nNewGridRows) * nNewGridCols;
412
0
        bool* pNewGridMap = new bool[nNewCellCount];
413
0
        size_t nOldCellCount = static_cast<size_t>(_nGridRows) * _nGridCols;
414
0
        memcpy(pNewGridMap, _pGridMap.get(), nOldCellCount * sizeof(bool));
415
0
        memset(pNewGridMap + nOldCellCount, 0, (nNewCellCount-nOldCellCount) * sizeof(bool));
416
0
        _pGridMap.reset( pNewGridMap );
417
0
        _nGridRows = nNewGridRows;
418
0
        _nGridCols = nNewGridCols;
419
0
    }
420
0
}
421
422
void IcnGridMap_Impl::Create_Impl()
423
0
{
424
0
    DBG_ASSERT(!_pGridMap,"Unnecessary call to IcnGridMap_Impl::Create_Impl()");
425
0
    if( _pGridMap )
426
0
        return;
427
0
    GetMinMapSize( _nGridCols, _nGridRows );
428
0
    _nGridCols += 50;
429
430
0
    size_t nCellCount = static_cast<size_t>(_nGridRows) * _nGridCols;
431
0
    _pGridMap.reset( new bool[nCellCount] );
432
0
    memset(_pGridMap.get(), 0, nCellCount * sizeof(bool));
433
434
0
    const size_t nCount = _pView->maEntries.size();
435
0
    for( size_t nCur=0; nCur < nCount; nCur++ )
436
0
        OccupyGrids( _pView->maEntries[ nCur ].get() );
437
0
}
438
439
void IcnGridMap_Impl::GetMinMapSize( sal_uInt16& rDX, sal_uInt16& rDY ) const
440
0
{
441
    // The view grows in horizontal direction. Its max. height is _pView->nMaxVirtHeight
442
0
    tools::Long nY = _pView->nMaxVirtHeight;
443
0
    if( !nY )
444
0
        nY = _pView->pView->GetOutputSizePixel().Height();
445
0
    if( !(_pView->nFlags & IconChoiceFlags::Arranging) )
446
0
        nY -= _pView->nHorSBarHeight;
447
448
0
    tools::Long nX = _pView->aVirtOutputSize.Width();
449
450
0
    if( !nX )
451
0
        nX = DEFAULT_MAX_VIRT_WIDTH;
452
0
    if( !nY )
453
0
        nY = DEFAULT_MAX_VIRT_HEIGHT;
454
455
0
    tools::Long nDX = nX / _pView->nGridDX;
456
0
    tools::Long nDY = nY / _pView->nGridDY;
457
458
0
    if( !nDX )
459
0
        nDX++;
460
0
    if( !nDY )
461
0
        nDY++;
462
463
0
    rDX = static_cast<sal_uInt16>(nDX);
464
0
    rDY = static_cast<sal_uInt16>(nDY);
465
0
}
466
467
GridId IcnGridMap_Impl::GetGrid( sal_uInt16 nGridX, sal_uInt16 nGridY )
468
0
{
469
0
    Create();
470
0
    return nGridY + ( static_cast<GridId>(nGridX) * _nGridRows );
471
0
}
472
473
GridId IcnGridMap_Impl::GetGrid( const Point& rDocPos )
474
0
{
475
0
    Create();
476
477
0
    tools::Long nX = rDocPos.X();
478
0
    tools::Long nY = rDocPos.Y();
479
0
    nX -= LROFFS_WINBORDER;
480
0
    nY -= TBOFFS_WINBORDER;
481
0
    nX /= _pView->nGridDX;
482
0
    nY /= _pView->nGridDY;
483
0
    if( nX >= _nGridCols )
484
0
    {
485
0
        nX = _nGridCols - 1;
486
0
    }
487
0
    if( nY >= _nGridRows )
488
0
    {
489
0
        nY = _nGridRows - 1;
490
0
    }
491
0
    GridId nId = GetGrid( static_cast<sal_uInt16>(nX), static_cast<sal_uInt16>(nY) );
492
0
    DBG_ASSERT(nId <o3tl::make_unsigned(_nGridCols*_nGridRows),"GetGrid failed");
493
0
    return nId;
494
0
}
495
496
tools::Rectangle IcnGridMap_Impl::GetGridRect( GridId nId )
497
0
{
498
0
    Create();
499
0
    sal_uInt16 nGridX, nGridY;
500
0
    GetGridCoord( nId, nGridX, nGridY );
501
0
    const tools::Long nLeft = nGridX * _pView->nGridDX+ LROFFS_WINBORDER;
502
0
    const tools::Long nTop = nGridY * _pView->nGridDY + TBOFFS_WINBORDER;
503
0
    return tools::Rectangle(
504
0
        nLeft, nTop,
505
0
        nLeft + _pView->nGridDX,
506
0
        nTop + _pView->nGridDY );
507
0
}
508
509
GridId IcnGridMap_Impl::GetUnoccupiedGrid()
510
0
{
511
0
    Create();
512
0
    sal_uLong nStart = 0;
513
0
    bool bExpanded = false;
514
515
0
    while( true )
516
0
    {
517
0
        const sal_uLong nCount = static_cast<sal_uInt16>(_nGridCols * _nGridRows);
518
0
        for( sal_uLong nCur = nStart; nCur < nCount; nCur++ )
519
0
        {
520
0
            if( !_pGridMap[ nCur ] )
521
0
            {
522
0
                _pGridMap[ nCur ] = true;
523
0
                return static_cast<GridId>(nCur);
524
0
            }
525
0
        }
526
0
        DBG_ASSERT(!bExpanded,"ExpandGrid failed");
527
0
        if( bExpanded )
528
0
            return 0; // prevent never ending loop
529
0
        bExpanded = true;
530
0
        Expand();
531
0
        nStart = nCount;
532
0
    }
533
0
}
534
535
// An entry only means that there's a GridRect lying under its center. This
536
// variant is much faster than allocating via the bounding rectangle but can
537
// lead to small overlaps.
538
void IcnGridMap_Impl::OccupyGrids( const SvxIconChoiceCtrlEntry* pEntry )
539
0
{
540
0
    if( !_pGridMap || !SvxIconChoiceCtrl_Impl::IsBoundingRectValid( pEntry->aRect ))
541
0
        return;
542
0
    OccupyGrid( GetGrid( pEntry->aRect.Center()) );
543
0
}
544
545
void IcnGridMap_Impl::Clear()
546
0
{
547
0
    if( _pGridMap )
548
0
    {
549
0
        _pGridMap.reset();
550
0
        _nGridRows = 0;
551
0
        _nGridCols = 0;
552
0
        _aLastOccupiedGrid.SetEmpty();
553
0
    }
554
0
}
555
556
sal_uLong IcnGridMap_Impl::GetGridCount( const Size& rSizePixel, sal_uInt16 nDX, sal_uInt16 nDY)
557
0
{
558
0
    tools::Long ndx = (rSizePixel.Width() - LROFFS_WINBORDER) / nDX;
559
0
    if( ndx < 0 ) ndx *= -1;
560
0
    tools::Long ndy = (rSizePixel.Height() - TBOFFS_WINBORDER) / nDY;
561
0
    if( ndy < 0 ) ndy *= -1;
562
0
    return static_cast<sal_uLong>(ndx * ndy);
563
0
}
564
565
void IcnGridMap_Impl::OutputSizeChanged()
566
0
{
567
0
    if( !_pGridMap )
568
0
        return;
569
570
0
    sal_uInt16 nCols, nRows;
571
0
    GetMinMapSize( nCols, nRows );
572
0
    if( nRows != _nGridRows )
573
0
        Clear();
574
0
    else if( nCols >= _nGridCols )
575
0
        Expand();
576
0
}
577
578
// the gridmap should contain the data in a continuous region, to make it possible
579
// to copy the whole block if the gridmap needs to be expanded.
580
void IcnGridMap_Impl::GetGridCoord( GridId nId, sal_uInt16& rGridX, sal_uInt16& rGridY )
581
0
{
582
0
    rGridX = static_cast<sal_uInt16>(nId / _nGridRows);
583
0
    rGridY = static_cast<sal_uInt16>(nId % _nGridRows);
584
0
}
585
586
587
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */