~ubuntu-branches/ubuntu/raring/agg/raring

« back to all changes in this revision

Viewing changes to .pc/06-fix-missing-includes.patch/include/agg_rasterizer_cells_aa.h

  • Committer: Package Import Robot
  • Author(s): Andrea Veri
  • Date: 2012-05-01 21:31:31 UTC
  • mfrom: (3.1.7 sid)
  • Revision ID: package-import@ubuntu.com-20120501213131-j45720h6afvr00zx
Tags: 2.5+dfsg1-7
* debian/patches/08-fix-kfreebsd-ftbfs.patch:
  - added to prevent a FTBFS on kfreebsd-*. (Closes: #671069)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//----------------------------------------------------------------------------
 
2
// Anti-Grain Geometry (AGG) - Version 2.5
 
3
// A high quality rendering engine for C++
 
4
// Copyright (C) 2002-2006 Maxim Shemanarev
 
5
// Contact: mcseem@antigrain.com
 
6
//          mcseemagg@yahoo.com
 
7
//          http://antigrain.com
 
8
// 
 
9
// AGG is free software; you can redistribute it and/or
 
10
// modify it under the terms of the GNU General Public License
 
11
// as published by the Free Software Foundation; either version 2
 
12
// of the License, or (at your option) any later version.
 
13
// 
 
14
// AGG is distributed in the hope that it will be useful,
 
15
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
// GNU General Public License for more details.
 
18
// 
 
19
// You should have received a copy of the GNU General Public License
 
20
// along with AGG; if not, write to the Free Software
 
21
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
 
22
// MA 02110-1301, USA.
 
23
//----------------------------------------------------------------------------
 
24
//
 
25
// The author gratefully acknowleges the support of David Turner, 
 
26
// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType 
 
27
// libray - in producing this work. See http://www.freetype.org for details.
 
28
//
 
29
//----------------------------------------------------------------------------
 
30
//
 
31
// Adaptation for 32-bit screen coordinates has been sponsored by 
 
32
// Liberty Technology Systems, Inc., visit http://lib-sys.com
 
33
//
 
34
// Liberty Technology Systems, Inc. is the provider of
 
35
// PostScript and PDF technology for software developers.
 
36
// 
 
37
//----------------------------------------------------------------------------
 
38
 
 
39
#ifndef AGG_RASTERIZER_CELLS_AA_INCLUDED
 
40
#define AGG_RASTERIZER_CELLS_AA_INCLUDED
 
41
 
 
42
#include <string.h>
 
43
#include <math.h>
 
44
#include "agg_math.h"
 
45
#include "agg_array.h"
 
46
 
 
47
 
 
48
namespace agg
 
49
{
 
50
 
 
51
    //-----------------------------------------------------rasterizer_cells_aa
 
52
    // An internal class that implements the main rasterization algorithm.
 
53
    // Used in the rasterizer. Should not be used direcly.
 
54
    template<class Cell> class rasterizer_cells_aa
 
55
    {
 
56
        enum cell_block_scale_e
 
57
        {
 
58
            cell_block_shift = 12,
 
59
            cell_block_size  = 1 << cell_block_shift,
 
60
            cell_block_mask  = cell_block_size - 1,
 
61
            cell_block_pool  = 256,
 
62
            cell_block_limit = 1024
 
63
        };
 
64
 
 
65
        struct sorted_y
 
66
        {
 
67
            unsigned start;
 
68
            unsigned num;
 
69
        };
 
70
 
 
71
    public:
 
72
        typedef Cell cell_type;
 
73
        typedef rasterizer_cells_aa<Cell> self_type;
 
74
 
 
75
        ~rasterizer_cells_aa();
 
76
        rasterizer_cells_aa();
 
77
 
 
78
        void reset();
 
79
        void style(const cell_type& style_cell);
 
80
        void line(int x1, int y1, int x2, int y2);
 
81
 
 
82
        int min_x() const { return m_min_x; }
 
83
        int min_y() const { return m_min_y; }
 
84
        int max_x() const { return m_max_x; }
 
85
        int max_y() const { return m_max_y; }
 
86
 
 
87
        void sort_cells();
 
88
 
 
89
        unsigned total_cells() const 
 
90
        {
 
91
            return m_num_cells;
 
92
        }
 
93
 
 
94
        unsigned scanline_num_cells(unsigned y) const 
 
95
        { 
 
96
            return m_sorted_y[y - m_min_y].num; 
 
97
        }
 
98
 
 
99
        const cell_type* const* scanline_cells(unsigned y) const
 
100
        { 
 
101
            return m_sorted_cells.data() + m_sorted_y[y - m_min_y].start; 
 
102
        }
 
103
 
 
104
        bool sorted() const { return m_sorted; }
 
105
 
 
106
    private:
 
107
        rasterizer_cells_aa(const self_type&);
 
108
        const self_type& operator = (const self_type&);
 
109
 
 
110
        void set_curr_cell(int x, int y);
 
111
        void add_curr_cell();
 
112
        void render_hline(int ey, int x1, int y1, int x2, int y2);
 
113
        void allocate_block();
 
114
        
 
115
    private:
 
116
        unsigned                m_num_blocks;
 
117
        unsigned                m_max_blocks;
 
118
        unsigned                m_curr_block;
 
119
        unsigned                m_num_cells;
 
120
        cell_type**             m_cells;
 
121
        cell_type*              m_curr_cell_ptr;
 
122
        pod_vector<cell_type*>  m_sorted_cells;
 
123
        pod_vector<sorted_y>    m_sorted_y;
 
124
        cell_type               m_curr_cell;
 
125
        cell_type               m_style_cell;
 
126
        int                     m_min_x;
 
127
        int                     m_min_y;
 
128
        int                     m_max_x;
 
129
        int                     m_max_y;
 
130
        bool                    m_sorted;
 
131
    };
 
132
 
 
133
 
 
134
 
 
135
 
 
136
    //------------------------------------------------------------------------
 
137
    template<class Cell> 
 
138
    rasterizer_cells_aa<Cell>::~rasterizer_cells_aa()
 
139
    {
 
140
        if(m_num_blocks)
 
141
        {
 
142
            cell_type** ptr = m_cells + m_num_blocks - 1;
 
143
            while(m_num_blocks--)
 
144
            {
 
145
                pod_allocator<cell_type>::deallocate(*ptr, cell_block_size);
 
146
                ptr--;
 
147
            }
 
148
            pod_allocator<cell_type*>::deallocate(m_cells, m_max_blocks);
 
149
        }
 
150
    }
 
151
 
 
152
    //------------------------------------------------------------------------
 
153
    template<class Cell> 
 
154
    rasterizer_cells_aa<Cell>::rasterizer_cells_aa() :
 
155
        m_num_blocks(0),
 
156
        m_max_blocks(0),
 
157
        m_curr_block(0),
 
158
        m_num_cells(0),
 
159
        m_cells(0),
 
160
        m_curr_cell_ptr(0),
 
161
        m_sorted_cells(),
 
162
        m_sorted_y(),
 
163
        m_min_x(0x7FFFFFFF),
 
164
        m_min_y(0x7FFFFFFF),
 
165
        m_max_x(-0x7FFFFFFF),
 
166
        m_max_y(-0x7FFFFFFF),
 
167
        m_sorted(false)
 
168
    {
 
169
        m_style_cell.initial();
 
170
        m_curr_cell.initial();
 
171
    }
 
172
 
 
173
    //------------------------------------------------------------------------
 
174
    template<class Cell> 
 
175
    void rasterizer_cells_aa<Cell>::reset()
 
176
    {
 
177
        m_num_cells = 0; 
 
178
        m_curr_block = 0;
 
179
        m_curr_cell.initial();
 
180
        m_style_cell.initial();
 
181
        m_sorted = false;
 
182
        m_min_x =  0x7FFFFFFF;
 
183
        m_min_y =  0x7FFFFFFF;
 
184
        m_max_x = -0x7FFFFFFF;
 
185
        m_max_y = -0x7FFFFFFF;
 
186
    }
 
187
 
 
188
    //------------------------------------------------------------------------
 
189
    template<class Cell> 
 
190
    AGG_INLINE void rasterizer_cells_aa<Cell>::add_curr_cell()
 
191
    {
 
192
        if(m_curr_cell.area | m_curr_cell.cover)
 
193
        {
 
194
            if((m_num_cells & cell_block_mask) == 0)
 
195
            {
 
196
                if(m_num_blocks >= cell_block_limit) return;
 
197
                allocate_block();
 
198
            }
 
199
            *m_curr_cell_ptr++ = m_curr_cell;
 
200
            ++m_num_cells;
 
201
        }
 
202
    }
 
203
 
 
204
    //------------------------------------------------------------------------
 
205
    template<class Cell> 
 
206
    AGG_INLINE void rasterizer_cells_aa<Cell>::set_curr_cell(int x, int y)
 
207
    {
 
208
        if(m_curr_cell.not_equal(x, y, m_style_cell))
 
209
        {
 
210
            add_curr_cell();
 
211
            m_curr_cell.style(m_style_cell);
 
212
            m_curr_cell.x     = x;
 
213
            m_curr_cell.y     = y;
 
214
            m_curr_cell.cover = 0;
 
215
            m_curr_cell.area  = 0;
 
216
        }
 
217
    }
 
218
 
 
219
    //------------------------------------------------------------------------
 
220
    template<class Cell> 
 
221
    AGG_INLINE void rasterizer_cells_aa<Cell>::render_hline(int ey, 
 
222
                                                            int x1, int y1, 
 
223
                                                            int x2, int y2)
 
224
    {
 
225
        int ex1 = x1 >> poly_subpixel_shift;
 
226
        int ex2 = x2 >> poly_subpixel_shift;
 
227
        int fx1 = x1 & poly_subpixel_mask;
 
228
        int fx2 = x2 & poly_subpixel_mask;
 
229
 
 
230
        int delta, p, first, dx;
 
231
        int incr, lift, mod, rem;
 
232
 
 
233
        //trivial case. Happens often
 
234
        if(y1 == y2)
 
235
        {
 
236
            set_curr_cell(ex2, ey);
 
237
            return;
 
238
        }
 
239
 
 
240
        //everything is located in a single cell.  That is easy!
 
241
        if(ex1 == ex2)
 
242
        {
 
243
            delta = y2 - y1;
 
244
            m_curr_cell.cover += delta;
 
245
            m_curr_cell.area  += (fx1 + fx2) * delta;
 
246
            return;
 
247
        }
 
248
 
 
249
        //ok, we'll have to render a run of adjacent cells on the same
 
250
        //hline...
 
251
        p     = (poly_subpixel_scale - fx1) * (y2 - y1);
 
252
        first = poly_subpixel_scale;
 
253
        incr  = 1;
 
254
 
 
255
        dx = x2 - x1;
 
256
 
 
257
        if(dx < 0)
 
258
        {
 
259
            p     = fx1 * (y2 - y1);
 
260
            first = 0;
 
261
            incr  = -1;
 
262
            dx    = -dx;
 
263
        }
 
264
 
 
265
        delta = p / dx;
 
266
        mod   = p % dx;
 
267
 
 
268
        if(mod < 0)
 
269
        {
 
270
            delta--;
 
271
            mod += dx;
 
272
        }
 
273
 
 
274
        m_curr_cell.cover += delta;
 
275
        m_curr_cell.area  += (fx1 + first) * delta;
 
276
 
 
277
        ex1 += incr;
 
278
        set_curr_cell(ex1, ey);
 
279
        y1  += delta;
 
280
 
 
281
        if(ex1 != ex2)
 
282
        {
 
283
            p     = poly_subpixel_scale * (y2 - y1 + delta);
 
284
            lift  = p / dx;
 
285
            rem   = p % dx;
 
286
 
 
287
            if (rem < 0)
 
288
            {
 
289
                lift--;
 
290
                rem += dx;
 
291
            }
 
292
 
 
293
            mod -= dx;
 
294
 
 
295
            while (ex1 != ex2)
 
296
            {
 
297
                delta = lift;
 
298
                mod  += rem;
 
299
                if(mod >= 0)
 
300
                {
 
301
                    mod -= dx;
 
302
                    delta++;
 
303
                }
 
304
 
 
305
                m_curr_cell.cover += delta;
 
306
                m_curr_cell.area  += poly_subpixel_scale * delta;
 
307
                y1  += delta;
 
308
                ex1 += incr;
 
309
                set_curr_cell(ex1, ey);
 
310
            }
 
311
        }
 
312
        delta = y2 - y1;
 
313
        m_curr_cell.cover += delta;
 
314
        m_curr_cell.area  += (fx2 + poly_subpixel_scale - first) * delta;
 
315
    }
 
316
 
 
317
    //------------------------------------------------------------------------
 
318
    template<class Cell> 
 
319
    AGG_INLINE void rasterizer_cells_aa<Cell>::style(const cell_type& style_cell)
 
320
    { 
 
321
        m_style_cell.style(style_cell); 
 
322
    }
 
323
 
 
324
    //------------------------------------------------------------------------
 
325
    template<class Cell> 
 
326
    void rasterizer_cells_aa<Cell>::line(int x1, int y1, int x2, int y2)
 
327
    {
 
328
        enum dx_limit_e { dx_limit = 16384 << poly_subpixel_shift };
 
329
 
 
330
        int dx = x2 - x1;
 
331
 
 
332
        if(dx >= dx_limit || dx <= -dx_limit)
 
333
        {
 
334
            int cx = (x1 + x2) >> 1;
 
335
            int cy = (y1 + y2) >> 1;
 
336
 
 
337
            // Bail if values are so large they are likely to wrap
 
338
            if ((std::abs(x1) >= std::numeric_limits<int>::max()/2) || (std::abs(y1) >= std::numeric_limits<int>::max()/2) ||
 
339
                (std::abs(x2) >= std::numeric_limits<int>::max()/2) || (std::abs(y2) >= std::numeric_limits<int>::max()/2))
 
340
                    return;
 
341
 
 
342
            line(x1, y1, cx, cy);
 
343
            line(cx, cy, x2, y2);
 
344
        }
 
345
 
 
346
        int dy = y2 - y1;
 
347
        int ex1 = x1 >> poly_subpixel_shift;
 
348
        int ex2 = x2 >> poly_subpixel_shift;
 
349
        int ey1 = y1 >> poly_subpixel_shift;
 
350
        int ey2 = y2 >> poly_subpixel_shift;
 
351
        int fy1 = y1 & poly_subpixel_mask;
 
352
        int fy2 = y2 & poly_subpixel_mask;
 
353
 
 
354
        int x_from, x_to;
 
355
        int p, rem, mod, lift, delta, first, incr;
 
356
 
 
357
        if(ex1 < m_min_x) m_min_x = ex1;
 
358
        if(ex1 > m_max_x) m_max_x = ex1;
 
359
        if(ey1 < m_min_y) m_min_y = ey1;
 
360
        if(ey1 > m_max_y) m_max_y = ey1;
 
361
        if(ex2 < m_min_x) m_min_x = ex2;
 
362
        if(ex2 > m_max_x) m_max_x = ex2;
 
363
        if(ey2 < m_min_y) m_min_y = ey2;
 
364
        if(ey2 > m_max_y) m_max_y = ey2;
 
365
 
 
366
        set_curr_cell(ex1, ey1);
 
367
 
 
368
        //everything is on a single hline
 
369
        if(ey1 == ey2)
 
370
        {
 
371
            render_hline(ey1, x1, fy1, x2, fy2);
 
372
            return;
 
373
        }
 
374
 
 
375
        //Vertical line - we have to calculate start and end cells,
 
376
        //and then - the common values of the area and coverage for
 
377
        //all cells of the line. We know exactly there's only one 
 
378
        //cell, so, we don't have to call render_hline().
 
379
        incr  = 1;
 
380
        if(dx == 0)
 
381
        {
 
382
            int ex = x1 >> poly_subpixel_shift;
 
383
            int two_fx = (x1 - (ex << poly_subpixel_shift)) << 1;
 
384
            int area;
 
385
 
 
386
            first = poly_subpixel_scale;
 
387
            if(dy < 0)
 
388
            {
 
389
                first = 0;
 
390
                incr  = -1;
 
391
            }
 
392
 
 
393
            x_from = x1;
 
394
 
 
395
            //render_hline(ey1, x_from, fy1, x_from, first);
 
396
            delta = first - fy1;
 
397
            m_curr_cell.cover += delta;
 
398
            m_curr_cell.area  += two_fx * delta;
 
399
 
 
400
            ey1 += incr;
 
401
            set_curr_cell(ex, ey1);
 
402
 
 
403
            delta = first + first - poly_subpixel_scale;
 
404
            area = two_fx * delta;
 
405
            while(ey1 != ey2)
 
406
            {
 
407
                //render_hline(ey1, x_from, poly_subpixel_scale - first, x_from, first);
 
408
                m_curr_cell.cover = delta;
 
409
                m_curr_cell.area  = area;
 
410
                ey1 += incr;
 
411
                set_curr_cell(ex, ey1);
 
412
            }
 
413
            //render_hline(ey1, x_from, poly_subpixel_scale - first, x_from, fy2);
 
414
            delta = fy2 - poly_subpixel_scale + first;
 
415
            m_curr_cell.cover += delta;
 
416
            m_curr_cell.area  += two_fx * delta;
 
417
            return;
 
418
        }
 
419
 
 
420
        //ok, we have to render several hlines
 
421
        p     = (poly_subpixel_scale - fy1) * dx;
 
422
        first = poly_subpixel_scale;
 
423
 
 
424
        if(dy < 0)
 
425
        {
 
426
            p     = fy1 * dx;
 
427
            first = 0;
 
428
            incr  = -1;
 
429
            dy    = -dy;
 
430
        }
 
431
 
 
432
        delta = p / dy;
 
433
        mod   = p % dy;
 
434
 
 
435
        if(mod < 0)
 
436
        {
 
437
            delta--;
 
438
            mod += dy;
 
439
        }
 
440
 
 
441
        x_from = x1 + delta;
 
442
        render_hline(ey1, x1, fy1, x_from, first);
 
443
 
 
444
        ey1 += incr;
 
445
        set_curr_cell(x_from >> poly_subpixel_shift, ey1);
 
446
 
 
447
        if(ey1 != ey2)
 
448
        {
 
449
            p     = poly_subpixel_scale * dx;
 
450
            lift  = p / dy;
 
451
            rem   = p % dy;
 
452
 
 
453
            if(rem < 0)
 
454
            {
 
455
                lift--;
 
456
                rem += dy;
 
457
            }
 
458
            mod -= dy;
 
459
 
 
460
            while(ey1 != ey2)
 
461
            {
 
462
                delta = lift;
 
463
                mod  += rem;
 
464
                if (mod >= 0)
 
465
                {
 
466
                    mod -= dy;
 
467
                    delta++;
 
468
                }
 
469
 
 
470
                x_to = x_from + delta;
 
471
                render_hline(ey1, x_from, poly_subpixel_scale - first, x_to, first);
 
472
                x_from = x_to;
 
473
 
 
474
                ey1 += incr;
 
475
                set_curr_cell(x_from >> poly_subpixel_shift, ey1);
 
476
            }
 
477
        }
 
478
        render_hline(ey1, x_from, poly_subpixel_scale - first, x2, fy2);
 
479
    }
 
480
 
 
481
    //------------------------------------------------------------------------
 
482
    template<class Cell> 
 
483
    void rasterizer_cells_aa<Cell>::allocate_block()
 
484
    {
 
485
        if(m_curr_block >= m_num_blocks)
 
486
        {
 
487
            if(m_num_blocks >= m_max_blocks)
 
488
            {
 
489
                cell_type** new_cells = 
 
490
                    pod_allocator<cell_type*>::allocate(m_max_blocks + 
 
491
                                                        cell_block_pool);
 
492
 
 
493
                if(m_cells)
 
494
                {
 
495
                    memcpy(new_cells, m_cells, m_max_blocks * sizeof(cell_type*));
 
496
                    pod_allocator<cell_type*>::deallocate(m_cells, m_max_blocks);
 
497
                }
 
498
                m_cells = new_cells;
 
499
                m_max_blocks += cell_block_pool;
 
500
            }
 
501
 
 
502
            m_cells[m_num_blocks++] = 
 
503
                pod_allocator<cell_type>::allocate(cell_block_size);
 
504
 
 
505
        }
 
506
        m_curr_cell_ptr = m_cells[m_curr_block++];
 
507
    }
 
508
 
 
509
 
 
510
 
 
511
    //------------------------------------------------------------------------
 
512
    template <class T> static AGG_INLINE void swap_cells(T* a, T* b)
 
513
    {
 
514
        T temp = *a;
 
515
        *a = *b;
 
516
        *b = temp;
 
517
    }
 
518
 
 
519
 
 
520
    //------------------------------------------------------------------------
 
521
    enum
 
522
    {
 
523
        qsort_threshold = 9
 
524
    };
 
525
 
 
526
 
 
527
    //------------------------------------------------------------------------
 
528
    template<class Cell>
 
529
    void qsort_cells(Cell** start, unsigned num)
 
530
    {
 
531
        Cell**  stack[80];
 
532
        Cell*** top; 
 
533
        Cell**  limit;
 
534
        Cell**  base;
 
535
 
 
536
        limit = start + num;
 
537
        base  = start;
 
538
        top   = stack;
 
539
 
 
540
        for (;;)
 
541
        {
 
542
            int len = int(limit - base);
 
543
 
 
544
            Cell** i;
 
545
            Cell** j;
 
546
            Cell** pivot;
 
547
 
 
548
            if(len > qsort_threshold)
 
549
            {
 
550
                // we use base + len/2 as the pivot
 
551
                pivot = base + len / 2;
 
552
                swap_cells(base, pivot);
 
553
 
 
554
                i = base + 1;
 
555
                j = limit - 1;
 
556
 
 
557
                // now ensure that *i <= *base <= *j 
 
558
                if((*j)->x < (*i)->x)
 
559
                {
 
560
                    swap_cells(i, j);
 
561
                }
 
562
 
 
563
                if((*base)->x < (*i)->x)
 
564
                {
 
565
                    swap_cells(base, i);
 
566
                }
 
567
 
 
568
                if((*j)->x < (*base)->x)
 
569
                {
 
570
                    swap_cells(base, j);
 
571
                }
 
572
 
 
573
                for(;;)
 
574
                {
 
575
                    int x = (*base)->x;
 
576
                    do i++; while( (*i)->x < x );
 
577
                    do j--; while( x < (*j)->x );
 
578
 
 
579
                    if(i > j)
 
580
                    {
 
581
                        break;
 
582
                    }
 
583
 
 
584
                    swap_cells(i, j);
 
585
                }
 
586
 
 
587
                swap_cells(base, j);
 
588
 
 
589
                // now, push the largest sub-array
 
590
                if(j - base > limit - i)
 
591
                {
 
592
                    top[0] = base;
 
593
                    top[1] = j;
 
594
                    base   = i;
 
595
                }
 
596
                else
 
597
                {
 
598
                    top[0] = i;
 
599
                    top[1] = limit;
 
600
                    limit  = j;
 
601
                }
 
602
                top += 2;
 
603
            }
 
604
            else
 
605
            {
 
606
                // the sub-array is small, perform insertion sort
 
607
                j = base;
 
608
                i = j + 1;
 
609
 
 
610
                for(; i < limit; j = i, i++)
 
611
                {
 
612
                    for(; j[1]->x < (*j)->x; j--)
 
613
                    {
 
614
                        swap_cells(j + 1, j);
 
615
                        if (j == base)
 
616
                        {
 
617
                            break;
 
618
                        }
 
619
                    }
 
620
                }
 
621
 
 
622
                if(top > stack)
 
623
                {
 
624
                    top  -= 2;
 
625
                    base  = top[0];
 
626
                    limit = top[1];
 
627
                }
 
628
                else
 
629
                {
 
630
                    break;
 
631
                }
 
632
            }
 
633
        }
 
634
    }
 
635
 
 
636
 
 
637
    //------------------------------------------------------------------------
 
638
    template<class Cell> 
 
639
    void rasterizer_cells_aa<Cell>::sort_cells()
 
640
    {
 
641
        if(m_sorted) return; //Perform sort only the first time.
 
642
 
 
643
        add_curr_cell();
 
644
        m_curr_cell.x     = 0x7FFFFFFF;
 
645
        m_curr_cell.y     = 0x7FFFFFFF;
 
646
        m_curr_cell.cover = 0;
 
647
        m_curr_cell.area  = 0;
 
648
 
 
649
        if(m_num_cells == 0) return;
 
650
 
 
651
// DBG: Check to see if min/max works well.
 
652
//for(unsigned nc = 0; nc < m_num_cells; nc++)
 
653
//{
 
654
//    cell_type* cell = m_cells[nc >> cell_block_shift] + (nc & cell_block_mask);
 
655
//    if(cell->x < m_min_x || 
 
656
//       cell->y < m_min_y || 
 
657
//       cell->x > m_max_x || 
 
658
//       cell->y > m_max_y)
 
659
//    {
 
660
//        cell = cell; // Breakpoint here
 
661
//    }
 
662
//}
 
663
        // Allocate the array of cell pointers
 
664
        m_sorted_cells.allocate(m_num_cells, 16);
 
665
 
 
666
        // Allocate and zero the Y array
 
667
        m_sorted_y.allocate(m_max_y - m_min_y + 1, 16);
 
668
        m_sorted_y.zero();
 
669
 
 
670
        // Create the Y-histogram (count the numbers of cells for each Y)
 
671
        cell_type** block_ptr = m_cells;
 
672
        cell_type*  cell_ptr;
 
673
        unsigned nb = m_num_cells >> cell_block_shift;
 
674
        unsigned i;
 
675
        while(nb--)
 
676
        {
 
677
            cell_ptr = *block_ptr++;
 
678
            i = cell_block_size;
 
679
            while(i--) 
 
680
            {
 
681
                m_sorted_y[cell_ptr->y - m_min_y].start++;
 
682
                ++cell_ptr;
 
683
            }
 
684
        }
 
685
 
 
686
        cell_ptr = *block_ptr++;
 
687
        i = m_num_cells & cell_block_mask;
 
688
        while(i--) 
 
689
        {
 
690
            m_sorted_y[cell_ptr->y - m_min_y].start++;
 
691
            ++cell_ptr;
 
692
        }
 
693
 
 
694
        // Convert the Y-histogram into the array of starting indexes
 
695
        unsigned start = 0;
 
696
        for(i = 0; i < m_sorted_y.size(); i++)
 
697
        {
 
698
            unsigned v = m_sorted_y[i].start;
 
699
            m_sorted_y[i].start = start;
 
700
            start += v;
 
701
        }
 
702
 
 
703
        // Fill the cell pointer array sorted by Y
 
704
        block_ptr = m_cells;
 
705
        nb = m_num_cells >> cell_block_shift;
 
706
        while(nb--)
 
707
        {
 
708
            cell_ptr = *block_ptr++;
 
709
            i = cell_block_size;
 
710
            while(i--) 
 
711
            {
 
712
                sorted_y& curr_y = m_sorted_y[cell_ptr->y - m_min_y];
 
713
                m_sorted_cells[curr_y.start + curr_y.num] = cell_ptr;
 
714
                ++curr_y.num;
 
715
                ++cell_ptr;
 
716
            }
 
717
        }
 
718
        
 
719
        cell_ptr = *block_ptr++;
 
720
        i = m_num_cells & cell_block_mask;
 
721
        while(i--) 
 
722
        {
 
723
            sorted_y& curr_y = m_sorted_y[cell_ptr->y - m_min_y];
 
724
            m_sorted_cells[curr_y.start + curr_y.num] = cell_ptr;
 
725
            ++curr_y.num;
 
726
            ++cell_ptr;
 
727
        }
 
728
 
 
729
        // Finally arrange the X-arrays
 
730
        for(i = 0; i < m_sorted_y.size(); i++)
 
731
        {
 
732
            const sorted_y& curr_y = m_sorted_y[i];
 
733
            if(curr_y.num)
 
734
            {
 
735
                qsort_cells(m_sorted_cells.data() + curr_y.start, curr_y.num);
 
736
            }
 
737
        }
 
738
        m_sorted = true;
 
739
    }
 
740
 
 
741
 
 
742
 
 
743
    //------------------------------------------------------scanline_hit_test
 
744
    class scanline_hit_test
 
745
    {
 
746
    public:
 
747
        scanline_hit_test(int x) : m_x(x), m_hit(false) {}
 
748
 
 
749
        void reset_spans() {}
 
750
        void finalize(int) {}
 
751
        void add_cell(int x, int)
 
752
        {
 
753
            if(m_x == x) m_hit = true;
 
754
        }
 
755
        void add_span(int x, int len, int)
 
756
        {
 
757
            if(m_x >= x && m_x < x+len) m_hit = true;
 
758
        }
 
759
        unsigned num_spans() const { return 1; }
 
760
        bool hit() const { return m_hit; }
 
761
 
 
762
    private:
 
763
        int  m_x;
 
764
        bool m_hit;
 
765
    };
 
766
 
 
767
 
 
768
}
 
769
 
 
770
#endif