osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarthSymbology/AGG.h

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 // Anti-Grain Geometry - Version 2.1 Lite 
00003 // Copyright (C) 2002-2003 Maxim Shemanarev (McSeem)
00004 //
00005 // Permission to copy, use, modify, sell and distribute this software 
00006 // is granted provided this copyright notice appears in all copies. 
00007 // This software is provided "as is" without express or implied
00008 // warranty, and with no claim as to its suitability for any purpose.
00009 //
00010 // The author gratefully acknowleges the support of David Turner, 
00011 // Robert Wilhelm, and Werner Lemberg - the authors of the FreeType 
00012 // libray - in producing this work. See http://www.freetype.org for details.
00013 //
00014 //----------------------------------------------------------------------------
00015 // Contact: mcseem@antigrain.com
00016 //          mcseemagg@yahoo.com
00017 //          http://www.antigrain.com
00018 //----------------------------------------------------------------------------
00019 #ifndef AGGLITE_H
00020 #define AGGLITE_H
00021 
00022 #include <memory.h>
00023 
00024 namespace agg
00025 {
00026     //------------------------------------------------------------------------
00027     typedef signed char    int8;
00028     typedef unsigned char  int8u;
00029     typedef signed short   int16;
00030     typedef unsigned short int16u;
00031     typedef signed int     int32;
00032     typedef unsigned int   int32u;
00033 
00034 
00035 
00036     //========================================================================
00037     struct rgba8 
00038     {
00039         enum order { rgb, bgr };
00040 
00041         int8u r;
00042         int8u g;
00043         int8u b;
00044         int8u a;
00045 
00046         //--------------------------------------------------------------------
00047         rgba8() {}
00048 
00049         //--------------------------------------------------------------------
00050         rgba8(unsigned r_, unsigned g_, unsigned b_, unsigned a_=255) :
00051             r(int8u(r_)), g(int8u(g_)), b(int8u(b_)), a(int8u(a_)) {}
00052 
00053         //--------------------------------------------------------------------
00054         rgba8(unsigned packed, order o) : 
00055             r((o == rgb) ? ((packed >> 16) & 0xFF) : (packed & 0xFF)),
00056             g((packed >> 8)  & 0xFF),
00057             b((o == rgb) ? (packed & 0xFF) : ((packed >> 16) & 0xFF)),
00058             a(255) {}
00059 
00060         //--------------------------------------------------------------------
00061         void opacity(double a_)
00062         {
00063             if(a_ < 0.0) a_ = 0.0;
00064             if(a_ > 1.0) a_ = 1.0;
00065             a = int8u(a_ * 255.0);
00066         }
00067 
00068         //--------------------------------------------------------------------
00069         double opacity() const
00070         {
00071             return double(a) / 255.0;
00072         }
00073 
00074         //--------------------------------------------------------------------
00075         rgba8 gradient(rgba8 c, double k) const
00076         {
00077             rgba8 ret;
00078             int ik = int(k * 256);
00079             ret.r = int8u(int(r) + (((int(c.r) - int(r)) * ik) >> 8));
00080             ret.g = int8u(int(g) + (((int(c.g) - int(g)) * ik) >> 8));
00081             ret.b = int8u(int(b) + (((int(c.b) - int(b)) * ik) >> 8));
00082             ret.a = int8u(int(a) + (((int(c.a) - int(a)) * ik) >> 8));
00083             return ret;
00084         }
00085 
00086         rgba8 pre() const
00087         {
00088             return rgba8((r*a) >> 8, (g*a) >> 8, (b*a) >> 8, a);
00089         }
00090     };
00091 
00092 
00093     //========================================================================
00094     // Rendering buffer wrapper. This class does not know anything about 
00095     // memory organizations, all it does it keeps an array of pointers 
00096     // to each pixel row. The general rules of rendering are as follows.
00097     // 
00098     // 1. Allocate or create somehow a rendering buffer itself. Since 
00099     //    the library does not depend on any particular platform or
00100     //    architecture it was decided that it's your responsibility 
00101     //    to create and destroy rendering buffers properly. You can use
00102     //    any available mechanism to create it - you can use a system API 
00103     //    function, simple memory allocation, or even statically defined array. 
00104     //    You also should know the memory organization (or possible variants)
00105     //    in your system. For example, there's an R,G,B or B,G,R organizations 
00106     //    with one byte per component (three byter per pixel) is used very often. 
00107     //    So, if you intend to use class render_bgr24, for example, you should 
00108     //    allocate at least width*height*3 bytes of memory.
00109     //
00110     // 2. Create a rendering_buffer object and then call method attach(). It requires
00111     //    a pointer to the buffer itself, width and height of the buffer in 
00112     //    pixels, and the length of the row in bytes. All these values must 
00113     //    properly correspond to the memory organization. The argument stride
00114     //    is used because in reality the row length in bytes does not obligatory 
00115     //    correspond with the width of the image in pixels, i.e. it cannot be 
00116     //    simply calculated as width_in_pixels * bytes_per_pixel. For example, 
00117     //    it must be aligned to 4 bytes in Windows bitmaps. Besides, the value
00118     //    of stride can be negative - it depends on the order of displaying
00119     //    the rendering buffer - from top to bottom or from bottom to top. 
00120     //    In other words, if stride > 0 the pointers to each row will start 
00121     //    from the beginning of the buffer and increase. If it < 0, the pointers 
00122     //    start from the end of the buffer and decrease. It gives you an 
00123     //    additional degree of freedom.
00124     //    Method attach() can be called more than once. The execution time of it
00125     //    is very little, still it allocates memory of heigh * sizeof(char*) bytes
00126     //    and has a loop while(height--) {...}, so it's unreasonable to call it
00127     //    every time before drawing any single pixel :-)
00128     //
00129     // 3. Create an object (or a number of objects) of a rendering class, such as
00130     //    renderer_bgr24_solid, renderer_bgr24_image and so on. These classes
00131     //    require a pointer to the renderer_buffer object, but they do not perform
00132     //    any considerable operations except storing this pointer. So, rendering
00133     //    objects can be created on demand almost any time. These objects know 
00134     //    about concrete memory organization (this knowledge is hardcoded), so 
00135     //    actually, the memory you allocated or created in clause 1 should 
00136     //    actually be in correspondence to the needs of the rendering class.
00137     //  
00138     // 4. Rener your image using rendering classes, for example, rasterizer
00139     //  
00140     // 5. Display the result, or store it, or whatever. It's also your 
00141     //    responsibility and depends on the platform.
00142     //------------------------------------------------------------------------
00143     class rendering_buffer
00144     {
00145     public:
00146         ~rendering_buffer();
00147 
00148         //-----------------------------------------Initialization
00149         rendering_buffer(unsigned char* buf,
00150                          unsigned width, 
00151                          unsigned height,
00152                          int      stride);
00153 
00154         //-----------------------------------------Initialization
00155         void attach(unsigned char* buf,
00156                     unsigned width, 
00157                     unsigned height,
00158                     int      stride);
00159 
00160         //-----------------------------------------Acessors
00161         const unsigned char* buf()    const { return m_buf;    }
00162         unsigned             width()  const { return m_width;  }
00163         unsigned             height() const { return m_height; }
00164         int                  stride() const { return m_stride; }
00165 
00166         bool inbox(int x, int y) const
00167         {
00168             return x >= 0 && y >= 0 && x < int(m_width) && y < int(m_height);
00169         }
00170         
00171         unsigned abs_stride() const 
00172         { 
00173             return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride); 
00174         }
00175 
00176         unsigned char* row(unsigned y) { return m_rows[y];  }
00177         const unsigned char* row(unsigned y) const { return m_rows[y]; }
00178         
00179     private:
00180         rendering_buffer(const rendering_buffer&);
00181         const rendering_buffer& operator = (const rendering_buffer&);
00182 
00183     private:
00184         unsigned char*  m_buf;        // Pointer to renrdering buffer
00185         unsigned char** m_rows;       // Pointers to each row of the buffer
00186         unsigned        m_width;      // Width in pixels
00187         unsigned        m_height;     // Height in pixels
00188         int             m_stride;     // Number of bytes per row. Can be < 0
00189         unsigned        m_max_height; // Maximal current height
00190     };
00191 
00192 
00193 
00194     //========================================================================
00195     //
00196     // This class is used to transfer data from class outline (or a similar one)
00197     // to the rendering buffer. It's organized very simple. The class stores 
00198     // information of horizontal spans to render it into a pixel-map buffer. 
00199     // Each span has initial X, length, and an array of bytes that determine the 
00200     // alpha-values for each pixel. So, the restriction of using this class is 256 
00201     // levels of Anti-Aliasing, which is quite enough for any practical purpose.
00202     // Before using this class you should know the minimal and maximal pixel 
00203     // coordinates of your scanline. The protocol of using is:
00204     // 1. reset(min_x, max_x)
00205     // 2. add_cell() / add_span() - accumulate scanline. You pass Y-coordinate 
00206     //    into these functions in order to make scanline know the last Y. Before 
00207     //    calling add_cell() / add_span() you should check with method is_ready(y)
00208     //    if the last Y has changed. It also checks if the scanline is not empty. 
00209     //    When forming one scanline the next X coordinate must be always greater
00210     //    than the last stored one, i.e. it works only with ordered coordinates.
00211     // 3. If the current scanline is_ready() you should render it and then call 
00212     //    reset_spans() before adding new cells/spans.
00213     //    
00214     // 4. Rendering:
00215     // 
00216     // Scanline provides an iterator class that allows you to extract
00217     // the spans and the cover values for each pixel. Be aware that clipping
00218     // has not been done yet, so you should perform it yourself.
00219     // Use scanline::iterator to render spans:
00220     //-------------------------------------------------------------------------
00221     //
00222     // int base_x = sl.base_x();          // base X. Should be added to the span's X
00223     //                                    // "sl" is a const reference to the 
00224     //                                    // scanline passed in.
00225     //
00226     // int y = sl.y();                    // Y-coordinate of the scanline
00227     //
00228     // ************************************
00229     // ...Perform vertical clipping here...
00230     // ************************************
00231     //
00232     // scanline::iterator span(sl);
00233     // 
00234     // unsigned char* row = m_rbuf->row(y); // The the address of the beginning 
00235     //                                      // of the current row
00236     // 
00237     // unsigned num_spans = sl.num_spans(); // Number of spans. It's guaranteed that
00238     //                                      // num_spans is always greater than 0.
00239     //
00240     // do
00241     // {
00242     //     int x = span.next() + base_x;        // The beginning X of the span
00243     //
00244     //     const int8u covers* = span.covers(); // The array of the cover values
00245     //
00246     //     int num_pix = span.num_pix();        // Number of pixels of the span.
00247     //                                          // Always greater than 0, still we
00248     //                                          // shoud use "int" instead of 
00249     //                                          // "unsigned" because it's more
00250     //                                          // convenient for clipping
00251     //
00252     //     **************************************
00253     //     ...Perform horizontal clipping here...
00254     //     ...you have x, covers, and pix_count..
00255     //     **************************************
00256     //
00257     //     unsigned char* dst = row + x;  // Calculate the start address of the row.
00258     //                                    // In this case we assume a simple 
00259     //                                    // grayscale image 1-byte per pixel.
00260     //     do
00261     //     {
00262     //         *dst++ = *covers++;        // Hypotetical rendering. 
00263     //     }
00264     //     while(--num_pix);
00265     // } 
00266     // while(--num_spans);  // num_spans cannot be 0, so this loop is quite safe
00267     //------------------------------------------------------------------------
00268     //
00269     // The question is: why should we accumulate the whole scanline when we
00270     // could render just separate spans when they're ready?
00271     // That's because using the scaline is in general faster. When is consists 
00272     // of more than one span the conditions for the processor cash system
00273     // are better, because switching between two different areas of memory 
00274     // (that can be large ones) occures less frequently.
00275     //------------------------------------------------------------------------
00276     class scanline
00277     {
00278     public:
00279         enum { aa_shift = 8 };
00280 
00281         class iterator
00282         {
00283         public:
00284             iterator(const scanline& sl) :
00285                 m_covers(sl.m_covers),
00286                 m_cur_count(sl.m_counts),
00287                 m_cur_start_ptr(sl.m_start_ptrs)
00288             {
00289             }
00290 
00291             int next()
00292             {
00293                 ++m_cur_count;
00294                 ++m_cur_start_ptr;
00295                 return int(*m_cur_start_ptr - m_covers);
00296             }
00297 
00298             int num_pix() const { return int(*m_cur_count); }
00299             const int8u* covers() const { return *m_cur_start_ptr; }
00300 
00301         private:
00302             const int8u*        m_covers;
00303             const int16u*       m_cur_count;
00304             const int8u* const* m_cur_start_ptr;
00305         };
00306 
00307         friend class iterator;
00308 
00309         ~scanline();
00310         scanline();
00311 
00312         void     reset(int min_x, int max_x, int dx=0, int dy=0);
00313 
00314         void     reset_spans();
00315         void     add_cell(int x, int y, unsigned cover);
00316         void     add_span(int x, int y, unsigned len, unsigned cover);
00317         int      is_ready(int y) const;
00318         int      base_x()    const { return m_min_x + m_dx;  }
00319         int      y()         const { return m_last_y + m_dy; }
00320         unsigned num_spans() const { return m_num_spans;     }
00321 
00322     private:
00323         scanline(const scanline&);
00324         const scanline& operator = (const scanline&);
00325 
00326     private:
00327         int      m_min_x;
00328         unsigned m_max_len;
00329         int      m_dx;
00330         int      m_dy;
00331         int      m_last_x;
00332         int      m_last_y;
00333         int8u*   m_covers;
00334         int8u**  m_start_ptrs;
00335         int16u*  m_counts;
00336         unsigned m_num_spans;
00337         int8u**  m_cur_start_ptr;
00338         int16u*  m_cur_count;
00339     };
00340 
00341 
00342     //------------------------------------------------------------------------
00343     inline void scanline::reset_spans()
00344     {
00345         m_last_x        = 0x7FFF;
00346         m_last_y        = 0x7FFF;
00347         m_cur_count     = m_counts;
00348         m_cur_start_ptr = m_start_ptrs;
00349         m_num_spans     = 0;
00350     }
00351 
00352 
00353     //------------------------------------------------------------------------
00354     inline void scanline::add_cell(int x, int y, unsigned cover)
00355     {
00356         x -= m_min_x;
00357         m_covers[x] = (unsigned char)cover;
00358         if(x == m_last_x+1)
00359         {
00360             (*m_cur_count)++;
00361         }
00362         else
00363         {
00364             *++m_cur_count = 1;
00365             *++m_cur_start_ptr = m_covers + x;
00366             m_num_spans++;
00367         }
00368         m_last_x = x;
00369         m_last_y = y;
00370     }
00371 
00372 
00373     //------------------------------------------------------------------------
00374     inline int scanline::is_ready(int y) const
00375     {
00376         return m_num_spans && (y ^ m_last_y);
00377     }
00378 
00379 
00380 
00381 
00382     //========================================================================
00383     // This class template is used basically for rendering scanlines. 
00384     // The 'Span' argument is one of the span renderers, such as span_rgb24 
00385     // and others.
00386     // 
00387     // Usage:
00388     // 
00389     //     // Creation
00390     //     agg::rendering_buffer rbuf(ptr, w, h, stride);
00391     //     agg::renderer<agg::span_rgb24> ren(rbuf);
00392     //     agg::rasterizer ras;
00393     //
00394     //     // Clear the frame buffer
00395     //     ren.clear(agg::rgba8(0,0,0));
00396     //
00397     //     // Making polygon
00398     //     // ras.move_to(. . .);
00399     //     // ras.line_to(. . .);
00400     //     // . . .
00401     //
00402     //     // Rendering
00403     //     ras.render(ren, agg::rgba8(200, 100, 80));
00404     //  
00405     //------------------------------------------------------------------------
00406     template<class Span> class renderer
00407     {
00408     public:
00409         //--------------------------------------------------------------------
00410         renderer(rendering_buffer& rbuf) : m_rbuf(&rbuf)
00411         {
00412         }
00413         
00414         //--------------------------------------------------------------------
00415         void clear(const rgba8& c)
00416         {
00417             unsigned y;
00418             for(y = 0; y < m_rbuf->height(); y++)
00419             {
00420                 m_span.hline(m_rbuf->row(y), 0, m_rbuf->width(), c);
00421             }
00422         }
00423 
00424         //--------------------------------------------------------------------
00425         void pixel(int x, int y, const rgba8& c)
00426         {
00427             if(m_rbuf->inbox(x, y))
00428             {
00429                 m_span.hline(m_rbuf->row(y), x, 1, c);
00430             }
00431         }
00432 
00433         //--------------------------------------------------------------------
00434         rgba8 pixel(int x, int y) const
00435         {
00436             if(m_rbuf->inbox(x, y))
00437             {
00438                 return m_span.get(m_rbuf->row(y), x);
00439             }
00440             return rgba8(0,0,0);
00441         }
00442 
00443         //--------------------------------------------------------------------
00444         void render(const scanline& sl, const rgba8& c)
00445         {
00446             if(sl.y() < 0 || sl.y() >= int(m_rbuf->height()))
00447             {
00448                 return;
00449             }
00450 
00451             unsigned num_spans = sl.num_spans();
00452             int base_x = sl.base_x();
00453             unsigned char* row = m_rbuf->row(sl.y());
00454             scanline::iterator span(sl);
00455 
00456             do
00457             {
00458                 int x = span.next() + base_x;
00459                 const int8u* covers = span.covers();
00460                 int num_pix = span.num_pix();
00461                 if(x < 0)
00462                 {
00463                     num_pix += x;
00464                     if(num_pix <= 0) continue;
00465                     covers -= x;
00466                     x = 0;
00467                 }
00468                 if(x + num_pix >= int(m_rbuf->width()))
00469                 {
00470                     num_pix = m_rbuf->width() - x;
00471                     if(num_pix <= 0) continue;
00472                 }
00473                 m_span.render(row, x, num_pix, covers, c);
00474             }
00475             while(--num_spans);
00476         }
00477 
00478         //--------------------------------------------------------------------
00479         rendering_buffer& rbuf() { return *m_rbuf; }
00480 
00481     private:
00482         rendering_buffer* m_rbuf;
00483         Span              m_span;
00484     };
00485 
00486 
00487     //------------------------------------------------------------------------
00488     // These constants determine the subpixel accuracy, to be more precise, 
00489     // the number of bits of the fractional part of the coordinates. 
00490     // The possible coordinate capacity in bits can be calculated by formula:
00491     // sizeof(int) * 8 - poly_base_shift * 2, i.e, for 32-bit integers and
00492     // 8-bits fractional part the capacity is 16 bits or [-32768...32767].
00493     enum
00494     {
00495         poly_base_shift = 8,
00496         poly_base_size  = 1 << poly_base_shift,
00497         poly_base_mask  = poly_base_size - 1
00498     };
00499     
00500     //------------------------------------------------------------------------
00501     inline int poly_coord(double c)
00502     {
00503         return int(c * poly_base_size);
00504     }
00505 
00506     //------------------------------------------------------------------------
00507     // A pixel cell. There're no constructors defined and it was done 
00508     // intentionally in order to avoid extra overhead when allocating an 
00509     // array of cells.
00510     struct cell
00511     {
00512         int16 x;
00513         int16 y;
00514         int   packed_coord;
00515         int   cover;
00516         int   area;
00517 
00518         void set(int x, int y, int c, int a);
00519         void set_coord(int x, int y);
00520         void set_cover(int c, int a);
00521         void add_cover(int c, int a);
00522     };
00523 
00524 
00525     //------------------------------------------------------------------------
00526     // An internal class that implements the main rasterization algorithm.
00527     // Used in the rasterizer. Should not be used direcly.
00528     class outline
00529     {
00530         enum
00531         {
00532             cell_block_shift = 12,
00533             cell_block_size  = 1 << cell_block_shift,
00534             cell_block_mask  = cell_block_size - 1,
00535             cell_block_pool  = 256,
00536             cell_block_limit = 1024
00537         };
00538 
00539     public:
00540 
00541         ~outline();
00542         outline();
00543 
00544         void reset();
00545 
00546         void move_to(int x, int y);
00547         void line_to(int x, int y);
00548 
00549         int min_x() const { return m_min_x; }
00550         int min_y() const { return m_min_y; }
00551         int max_x() const { return m_max_x; }
00552         int max_y() const { return m_max_y; }
00553 
00554         unsigned num_cells() const {return m_num_cells; }
00555         const cell* const* cells();
00556 
00557     private:
00558         outline(const outline&);
00559         const outline& operator = (const outline&);
00560 
00561         void set_cur_cell(int x, int y);
00562         void add_cur_cell();
00563         void sort_cells();
00564         void render_scanline(int ey, int x1, int y1, int x2, int y2);
00565         void render_line(int x1, int y1, int x2, int y2);
00566         void allocate_block();
00567         
00568         static void qsort_cells(cell** start, unsigned num);
00569 
00570     private:
00571         unsigned  m_num_blocks;
00572         unsigned  m_max_blocks;
00573         unsigned  m_cur_block;
00574         unsigned  m_num_cells;
00575         cell**    m_cells;
00576         cell*     m_cur_cell_ptr;
00577         cell**    m_sorted_cells;
00578         unsigned  m_sorted_size;
00579         cell      m_cur_cell;
00580         int       m_cur_x;
00581         int       m_cur_y;
00582         int       m_close_x;
00583         int       m_close_y;
00584         int       m_min_x;
00585         int       m_min_y;
00586         int       m_max_x;
00587         int       m_max_y;
00588         unsigned  m_flags;
00589     };
00590 
00591 
00592     //------------------------------------------------------------------------
00593     enum filling_rule_e
00594     {
00595         fill_non_zero,
00596         fill_even_odd
00597     };
00598     
00599 
00600     //========================================================================
00601     // Polygon rasterizer that is used to render filled polygons with 
00602     // high-quality Anti-Aliasing. Internally, by default, the class uses 
00603     // integer coordinates in format 24.8, i.e. 24 bits for integer part 
00604     // and 8 bits for fractional - see poly_base_shift. This class can be 
00605     // used in the following  way:
00606     //
00607     // 1. filling_rule(filling_rule_e ft) - optional.
00608     //
00609     // 2. gamma() - optional.
00610     //
00611     // 3. reset()
00612     //
00613     // 4. move_to(x, y) / line_to(x, y) - make the polygon. One can create 
00614     //    more than one contour, but each contour must consist of at least 3
00615     //    vertices, i.e. move_to(x1, y1); line_to(x2, y2); line_to(x3, y3);
00616     //    is the absolute minimum of vertices that define a triangle.
00617     //    The algorithm does not check either the number of vertices nor
00618     //    coincidence of their coordinates, but in the worst case it just 
00619     //    won't draw anything.
00620     //    The orger of the vertices (clockwise or counterclockwise) 
00621     //    is important when using the non-zero filling rule (fill_non_zero).
00622     //    In this case the vertex order of all the contours must be the same
00623     //    if you want your intersecting polygons to be without "holes".
00624     //    You actually can use different vertices order. If the contours do not 
00625     //    intersect each other the order is not important anyway. If they do, 
00626     //    contours with the same vertex order will be rendered without "holes" 
00627     //    while the intersecting contours with different orders will have "holes".
00628     //
00629     // filling_rule() and gamma() can be called anytime before "sweeping".
00630     //------------------------------------------------------------------------
00631     class rasterizer
00632     {
00633     public:
00634         enum
00635         {
00636             aa_shift = scanline::aa_shift,
00637             aa_num   = 1 << aa_shift,
00638             aa_mask  = aa_num - 1,
00639             aa_2num  = aa_num * 2,
00640             aa_2mask = aa_2num - 1
00641         };
00642 
00643         rasterizer() :
00644             m_filling_rule(fill_non_zero)
00645         {
00646             memcpy(m_gamma, s_default_gamma, sizeof(m_gamma));
00647         }
00648 
00649         //--------------------------------------------------------------------
00650         void reset() { m_outline.reset(); }
00651 
00652         //--------------------------------------------------------------------
00653         void filling_rule(filling_rule_e filling_rule) 
00654         { 
00655             m_filling_rule = filling_rule; 
00656         }
00657 
00658         //--------------------------------------------------------------------
00659         void gamma(double g);
00660         void gamma(const int8u* g);
00661 
00662         //--------------------------------------------------------------------
00663         void move_to(int x, int y) { m_outline.move_to(x, y); }
00664         void line_to(int x, int y) { m_outline.line_to(x, y); }
00665 
00666         //--------------------------------------------------------------------
00667         void move_to_d(double x, double y) { m_outline.move_to(poly_coord(x), 
00668                                                                poly_coord(y)); }
00669         void line_to_d(double x, double y) { m_outline.line_to(poly_coord(x), 
00670                                                                poly_coord(y)); }
00671 
00672         //--------------------------------------------------------------------
00673         int min_x() const { return m_outline.min_x(); }
00674         int min_y() const { return m_outline.min_y(); }
00675         int max_x() const { return m_outline.max_x(); }
00676         int max_y() const { return m_outline.max_y(); }
00677 
00678         //--------------------------------------------------------------------
00679         unsigned calculate_alpha(int area) const
00680         {
00681             int cover = area >> (poly_base_shift*2 + 1 - aa_shift);
00682 
00683             if(cover < 0) cover = -cover;
00684             if(m_filling_rule == fill_even_odd)
00685             {
00686                 cover &= aa_2mask;
00687                 if(cover > aa_num)
00688                 {
00689                     cover = aa_2num - cover;
00690                 }
00691             }
00692             if(cover > aa_mask) cover = aa_mask;
00693             return cover;
00694         }
00695 
00696         //--------------------------------------------------------------------
00697         template<class Renderer> void render(Renderer& r, 
00698                                              const rgba8& c, 
00699                                              int dx=0, 
00700                                              int dy=0)
00701         {
00702             const cell* const* cells = m_outline.cells();
00703             if(m_outline.num_cells() == 0) return;
00704 
00705             int x, y;
00706             int cover;
00707             int alpha;
00708             int area;
00709 
00710             m_scanline.reset(m_outline.min_x(), m_outline.max_x(), dx, dy);
00711 
00712             cover = 0;
00713             const cell* cur_cell = *cells++;
00714             for(;;)
00715             {
00716                 const cell* start_cell = cur_cell;
00717 
00718                 int coord  = cur_cell->packed_coord;
00719                 x = cur_cell->x;
00720                 y = cur_cell->y;
00721 
00722                 area   = start_cell->area;
00723                 cover += start_cell->cover;
00724 
00725                 //accumulate all start cells
00726                 while((cur_cell = *cells++) != 0)
00727                 {
00728                     if(cur_cell->packed_coord != coord) break;
00729                     area  += cur_cell->area;
00730                     cover += cur_cell->cover;
00731                 }
00732 
00733                 if(area)
00734                 {
00735                     alpha = calculate_alpha((cover << (poly_base_shift + 1)) - area);
00736                     if(alpha)
00737                     {
00738                         if(m_scanline.is_ready(y))
00739                         {
00740                             r.render(m_scanline, c);
00741                             m_scanline.reset_spans();
00742                         }
00743                         m_scanline.add_cell(x, y, m_gamma[alpha]);
00744                     }
00745                     x++;
00746                 }
00747 
00748                 if(!cur_cell) break;
00749 
00750                 if(cur_cell->x > x)
00751                 {
00752                     alpha = calculate_alpha(cover << (poly_base_shift + 1));
00753                     if(alpha)
00754                     {
00755                         if(m_scanline.is_ready(y))
00756                         {
00757                             r.render(m_scanline, c);
00758                             m_scanline.reset_spans();
00759                         }
00760                         m_scanline.add_span(x, y, 
00761                                             cur_cell->x - x, 
00762                                             m_gamma[alpha]);
00763                     }
00764                 }
00765             } 
00766         
00767             if(m_scanline.num_spans())
00768             {
00769                 r.render(m_scanline, c);
00770             }
00771         }
00772 
00773 
00774         //--------------------------------------------------------------------
00775         bool hit_test(int tx, int ty);
00776 
00777     private:
00778         rasterizer(const rasterizer&);
00779         const rasterizer& operator = (const rasterizer&);
00780 
00781     private:
00782         outline        m_outline;
00783         scanline       m_scanline;
00784         filling_rule_e m_filling_rule;
00785         int8u          m_gamma[256];
00786         static const int8u s_default_gamma[256];     
00787     };
00788 
00789 
00790     //========================================================================
00791     struct span_mono8
00792     {
00793         //--------------------------------------------------------------------
00794         static unsigned mono8(unsigned r, unsigned g, unsigned b)
00795         {
00796             return (r * 77 + g * 150 + b * 29) >> 8;
00797         }
00798 
00799         //--------------------------------------------------------------------
00800         static void render(unsigned char* ptr, 
00801                            int x,
00802                            unsigned count, 
00803                            const unsigned char* covers, 
00804                            const rgba8& c)
00805         {
00806             unsigned char* p = ptr + x;
00807             unsigned dst = mono8(c.r, c.g, c.b);
00808             do
00809             {
00810                 int alpha = (*covers++) * c.a;
00811                 unsigned src = *p;
00812                 *p++ = (((dst - src) * alpha) + (src << 16)) >> 16;
00813             }
00814             while(--count);
00815         }
00816 
00817         //--------------------------------------------------------------------
00818         static void hline(unsigned char* ptr, 
00819                           int x,
00820                           unsigned count, 
00821                           const rgba8& c)
00822         {
00823             unsigned char* p = ptr + x;
00824             unsigned v = mono8(c.r, c.g, c.b);
00825             do { *p++ = v; } while(--count);
00826         }
00827 
00828         //--------------------------------------------------------------------
00829         static rgba8 get(unsigned char* ptr, int x)
00830         {
00831             unsigned rgb = ptr[x];
00832             rgba8 c;
00833             c.r = rgb; 
00834             c.g = rgb; 
00835             c.b = rgb;
00836             c.a = 255;
00837             return c;
00838         }
00839     };
00840 
00841 
00842 
00843     //========================================================================
00844     struct span_rgb555
00845     {
00846         //--------------------------------------------------------------------
00847         static int16u rgb555(unsigned r, unsigned g, unsigned b)
00848         {
00849             return ((r & 0xF8) << 7) | ((g & 0xF8) << 2) | (b >> 3);
00850         }
00851 
00852         //--------------------------------------------------------------------
00853         static void render(unsigned char* ptr, 
00854                            int x,
00855                            unsigned count, 
00856                            const unsigned char* covers, 
00857                            const rgba8& c)
00858         {
00859             int16u* p = ((int16u*)ptr) + x;
00860             do
00861             {
00862                 int16 rgb = *p;
00863                 int alpha = (*covers++) * c.a;
00864 
00865                 int r = (rgb >> 7) & 0xF8;
00866                 int g = (rgb >> 2) & 0xF8;
00867                 int b = (rgb << 3) & 0xF8;
00868 
00869                 *p++ = (((((c.r - r) * alpha) + (r << 16)) >> 9) & 0x7C00) |
00870                        (((((c.g - g) * alpha) + (g << 16)) >> 14) & 0x3E0) |
00871                         ((((c.b - b) * alpha) + (b << 16)) >> 19);
00872             }
00873             while(--count);
00874         }
00875 
00876         //--------------------------------------------------------------------
00877         static void hline(unsigned char* ptr, 
00878                           int x,
00879                           unsigned count, 
00880                           const rgba8& c)
00881         {
00882             int16u* p = ((int16u*)ptr) + x;
00883             int16u  v = rgb555(c.r, c.g, c.b);
00884             do { *p++ = v; } while(--count);
00885         }
00886 
00887         //--------------------------------------------------------------------
00888         static rgba8 get(unsigned char* ptr, int x)
00889         {
00890             int16u rgb = ((int16u*)ptr)[x];
00891             rgba8 c;
00892             c.r = (rgb >> 7) & 0xF8; 
00893             c.g = (rgb >> 2) & 0xF8; 
00894             c.b = (rgb << 3) & 0xF8;
00895             c.a = 255;
00896             return c;
00897         }
00898     };
00899 
00900 
00901 
00902 
00903     //========================================================================
00904     struct span_rgb565
00905     {
00906         //--------------------------------------------------------------------
00907         static int16u rgb565(unsigned r, unsigned g, unsigned b)
00908         {
00909             return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
00910         }
00911 
00912         //--------------------------------------------------------------------
00913         static void render(unsigned char* ptr, 
00914                            int x,
00915                            unsigned count, 
00916                            const unsigned char* covers, 
00917                            const rgba8& c)
00918         {
00919             int16u* p = ((int16u*)ptr) + x;
00920             do
00921             {
00922                 int16 rgb = *p;
00923                 int alpha = (*covers++) * c.a;
00924 
00925                 int r = (rgb >> 8) & 0xF8;
00926                 int g = (rgb >> 3) & 0xFC;
00927                 int b = (rgb << 3) & 0xF8;
00928 
00929                 *p++ = (((((c.r - r) * alpha) + (r << 16)) >> 8) & 0xF800) |
00930                        (((((c.g - g) * alpha) + (g << 16)) >> 13) & 0x7E0) |
00931                         ((((c.b - b) * alpha) + (b << 16)) >> 19);
00932             }
00933             while(--count);
00934         }
00935 
00936         //--------------------------------------------------------------------
00937         static void hline(unsigned char* ptr, 
00938                           int x,
00939                           unsigned count, 
00940                           const rgba8& c)
00941         {
00942             int16u* p = ((int16u*)ptr) + x;
00943             int16u  v = rgb565(c.r, c.g, c.b);
00944             do { *p++ = v; } while(--count);
00945         }
00946 
00947         //--------------------------------------------------------------------
00948         static rgba8 get(unsigned char* ptr, int x)
00949         {
00950             int16u rgb = ((int16u*)ptr)[x];
00951             rgba8 c;
00952             c.r = (rgb >> 8) & 0xF8; 
00953             c.g = (rgb >> 3) & 0xFC; 
00954             c.b = (rgb << 3) & 0xF8;
00955             c.a = 255;
00956             return c;
00957         }
00958     };
00959 
00960 
00961 
00962     //========================================================================
00963     struct span_bgr24
00964     {
00965         //--------------------------------------------------------------------
00966         static void render(unsigned char* ptr, 
00967                            int x,
00968                            unsigned count, 
00969                            const unsigned char* covers, 
00970                            const rgba8& c)
00971         {
00972             unsigned char* p = ptr + x + x + x;
00973             do
00974             {
00975                 int alpha = (*covers++) * c.a;
00976                 int b = p[0];
00977                 int g = p[1];
00978                 int r = p[2];
00979                 *p++ = (((c.b - b) * alpha) + (b << 16)) >> 16;
00980                 *p++ = (((c.g - g) * alpha) + (g << 16)) >> 16;
00981                 *p++ = (((c.r - r) * alpha) + (r << 16)) >> 16;
00982             }
00983             while(--count);
00984         }
00985 
00986         //--------------------------------------------------------------------
00987         static void hline(unsigned char* ptr, 
00988                           int x,
00989                           unsigned count, 
00990                           const rgba8& c)
00991         {
00992             unsigned char* p = ptr + x + x + x;
00993             do { *p++ = c.b; *p++ = c.g; *p++ = c.r; } while(--count);
00994         }
00995 
00996         //--------------------------------------------------------------------
00997         static rgba8 get(unsigned char* ptr, int x)
00998         {
00999             unsigned char* p = ptr + x + x + x;
01000             rgba8 c;
01001             c.b = *p++; 
01002             c.g = *p++; 
01003             c.r = *p++;
01004             c.a = 255;
01005             return c;
01006         }
01007     };
01008 
01009 
01010 
01011     //========================================================================
01012     struct span_rgb24
01013     {
01014         //--------------------------------------------------------------------
01015         static void render(unsigned char* ptr, 
01016                            int x,
01017                            unsigned count, 
01018                            const unsigned char* covers, 
01019                            const rgba8& c)
01020         {
01021             unsigned char* p = ptr + x + x + x;
01022             do
01023             {
01024                 int alpha = (*covers++) * c.a;
01025                 int r = p[0];
01026                 int g = p[1];
01027                 int b = p[2];
01028                 *p++ = (((c.r - r) * alpha) + (r << 16)) >> 16;
01029                 *p++ = (((c.g - g) * alpha) + (g << 16)) >> 16;
01030                 *p++ = (((c.b - b) * alpha) + (b << 16)) >> 16;
01031             }
01032             while(--count);
01033         }
01034 
01035         //--------------------------------------------------------------------
01036         static void hline(unsigned char* ptr, 
01037                           int x,
01038                           unsigned count, 
01039                           const rgba8& c)
01040         {
01041             unsigned char* p = ptr + x + x + x;
01042             do { *p++ = c.r; *p++ = c.g; *p++ = c.b; } while(--count);
01043         }
01044 
01045         //--------------------------------------------------------------------
01046         static rgba8 get(unsigned char* ptr, int x)
01047         {
01048             unsigned char* p = ptr + x + x + x;
01049             rgba8 c;
01050             c.r = *p++; 
01051             c.g = *p++; 
01052             c.b = *p++;
01053             c.a = 255;
01054             return c;
01055         }
01056     };
01057 
01058 
01059 
01060     //========================================================================
01061     struct span_abgr32
01062     {
01063         //--------------------------------------------------------------------
01064         static void render(unsigned char* ptr, 
01065                            int x,
01066                            unsigned count, 
01067                            const unsigned char* covers, 
01068                            const rgba8& c)
01069         {
01070             unsigned char* p = ptr + (x << 2);
01071             do
01072             {
01073                 int alpha = (*covers++) * c.a;
01074                 int a = p[0];
01075                 int b = p[1];
01076                 int g = p[2];
01077                 int r = p[3];
01078                 *p++ = (((c.a - a) * alpha) + (a << 16)) >> 16;
01079                 *p++ = (((c.b - b) * alpha) + (b << 16)) >> 16;
01080                 *p++ = (((c.g - g) * alpha) + (g << 16)) >> 16;
01081                 *p++ = (((c.r - r) * alpha) + (r << 16)) >> 16;
01082             }
01083             while(--count);
01084         }
01085 
01086         //--------------------------------------------------------------------
01087         static void hline(unsigned char* ptr, 
01088                           int x,
01089                           unsigned count, 
01090                           const rgba8& c)
01091         {
01092             unsigned char* p = ptr + (x << 2);
01093             do { *p++ = c.a; *p++ = c.b; *p++ = c.g; *p++ = c.r; } while(--count);
01094         }
01095 
01096         //--------------------------------------------------------------------
01097         static rgba8 get(unsigned char* ptr, int x)
01098         {
01099             unsigned char* p = ptr + (x << 2);
01100             rgba8 c;
01101             c.a = *p++; 
01102             c.b = *p++; 
01103             c.g = *p++;
01104             c.r = *p;
01105             return c;
01106         }
01107     };
01108 
01109 
01110 
01111 
01112     //========================================================================
01113     struct span_argb32
01114     {
01115         //--------------------------------------------------------------------
01116         static void render(unsigned char* ptr, 
01117                            int x,
01118                            unsigned count, 
01119                            const unsigned char* covers, 
01120                            const rgba8& c)
01121         {
01122             unsigned char* p = ptr + (x << 2);
01123             do
01124             {
01125                 int alpha = (*covers++) * c.a;
01126                 int a = p[0];
01127                 int r = p[1];
01128                 int g = p[2];
01129                 int b = p[3];
01130                 *p++ = (((c.a - a) * alpha) + (a << 16)) >> 16;
01131                 *p++ = (((c.r - r) * alpha) + (r << 16)) >> 16;
01132                 *p++ = (((c.g - g) * alpha) + (g << 16)) >> 16;
01133                 *p++ = (((c.b - b) * alpha) + (b << 16)) >> 16;
01134             }
01135             while(--count);
01136         }
01137 
01138         //--------------------------------------------------------------------
01139         static void hline(unsigned char* ptr, 
01140                           int x,
01141                           unsigned count, 
01142                           const rgba8& c)
01143         {
01144             unsigned char* p = ptr + (x << 2);
01145             do { *p++ = c.a; *p++ = c.r; *p++ = c.g; *p++ = c.b; } while(--count);
01146         }
01147 
01148         //--------------------------------------------------------------------
01149         static rgba8 get(unsigned char* ptr, int x)
01150         {
01151             unsigned char* p = ptr + (x << 2);
01152             rgba8 c;
01153             c.a = *p++; 
01154             c.r = *p++; 
01155             c.g = *p++;
01156             c.b = *p;
01157             return c;
01158         }
01159     };
01160 
01161 
01162 
01163     //========================================================================
01164     struct span_bgra32
01165     {
01166         //--------------------------------------------------------------------
01167         static void render(unsigned char* ptr, 
01168                            int x,
01169                            unsigned count, 
01170                            const unsigned char* covers, 
01171                            const rgba8& c)
01172         {
01173             unsigned char* p = ptr + (x << 2);
01174             do
01175             {
01176                 int alpha = (*covers++) * c.a;
01177                 int b = p[0];
01178                 int g = p[1];
01179                 int r = p[2];
01180                 int a = p[3];
01181                 *p++ = (((c.b - b) * alpha) + (b << 16)) >> 16;
01182                 *p++ = (((c.g - g) * alpha) + (g << 16)) >> 16;
01183                 *p++ = (((c.r - r) * alpha) + (r << 16)) >> 16;
01184                 *p++ = (((c.a - a) * alpha) + (a << 16)) >> 16;
01185             }
01186             while(--count);
01187         }
01188 
01189         //--------------------------------------------------------------------
01190         static void hline(unsigned char* ptr, 
01191                           int x,
01192                           unsigned count, 
01193                           const rgba8& c)
01194         {
01195             unsigned char* p = ptr + (x << 2);
01196             do { *p++ = c.b; *p++ = c.g; *p++ = c.r; *p++ = c.a; } while(--count);
01197         }
01198 
01199         //--------------------------------------------------------------------
01200         static rgba8 get(unsigned char* ptr, int x)
01201         {
01202             unsigned char* p = ptr + (x << 2);
01203             rgba8 c;
01204             c.b = *p++; 
01205             c.g = *p++; 
01206             c.r = *p++;
01207             c.a = *p;
01208             return c;
01209         }
01210     };
01211 
01212 
01213 
01214 
01215     //========================================================================
01216     struct span_rgba32
01217     {
01218         //--------------------------------------------------------------------
01219         static void render(unsigned char* ptr, 
01220                            int x,
01221                            unsigned count, 
01222                            const unsigned char* covers, 
01223                            const rgba8& c)
01224         {
01225             unsigned char* p = ptr + (x << 2);
01226             do
01227             {
01228                 int alpha = (*covers++) * c.a;
01229                 int r = p[0];
01230                 int g = p[1];
01231                 int b = p[2];
01232                 int a = p[3];
01233                 *p++ = (((c.r - r) * alpha) + (r << 16)) >> 16;
01234                 *p++ = (((c.g - g) * alpha) + (g << 16)) >> 16;
01235                 *p++ = (((c.b - b) * alpha) + (b << 16)) >> 16;
01236                 *p++ = (((c.a - a) * alpha) + (a << 16)) >> 16;
01237             }
01238             while(--count);
01239         }
01240 
01241         //--------------------------------------------------------------------
01242         static void hline(unsigned char* ptr, 
01243                           int x,
01244                           unsigned count, 
01245                           const rgba8& c)
01246         {
01247             unsigned char* p = ptr + (x << 2);
01248             do { *p++ = c.r; *p++ = c.g; *p++ = c.b; *p++ = c.a; } while(--count);
01249         }
01250 
01251         //--------------------------------------------------------------------
01252         static rgba8 get(unsigned char* ptr, int x)
01253         {
01254             unsigned char* p = ptr + (x << 2);
01255             rgba8 c;
01256             c.r = *p++; 
01257             c.g = *p++; 
01258             c.b = *p++;
01259             c.a = *p;
01260             return c;
01261         }
01262     };
01263 }
01264 
01265 // ===== agg.cpp ===== //
01266 
01267 namespace agg
01268 {
01269     //========================================================================
01270 
01271     //------------------------------------------------------------------------
01272     rendering_buffer::~rendering_buffer()
01273     {
01274         delete [] m_rows;
01275     }
01276 
01277 
01278     //------------------------------------------------------------------------
01279     rendering_buffer::rendering_buffer(unsigned char* buf,
01280                                        unsigned width, 
01281                                        unsigned height,
01282                                        int      stride) :
01283         m_buf(0),
01284         m_rows(0),
01285         m_width(0),
01286         m_height(0),
01287         m_stride(0),
01288         m_max_height(0)
01289     {
01290         attach(buf, width, height, stride);
01291     }
01292 
01293 
01294     //------------------------------------------------------------------------
01295     void rendering_buffer::attach(unsigned char* buf,
01296                                   unsigned width, 
01297                                   unsigned height,
01298                                   int      stride)
01299     {
01300         m_buf = buf;
01301         m_width = width;
01302         m_height = height;
01303         m_stride = stride;
01304         if(height > m_max_height)
01305         {
01306             delete [] m_rows;
01307             m_rows = new unsigned char* [m_max_height = height];
01308         }
01309 
01310         unsigned char* row_ptr = m_buf;
01311 
01312         if(stride < 0)
01313         {
01314             row_ptr = m_buf - int(height - 1) * stride;
01315         }
01316 
01317         unsigned char** rows = m_rows;
01318 
01319         while(height--)
01320         {
01321             *rows++ = row_ptr;
01322             row_ptr += stride;
01323         }
01324     }
01325 
01326 
01327     //========================================================================
01328 
01329     //------------------------------------------------------------------------
01330     scanline::~scanline()
01331     {
01332         if ( m_counts ) delete [] m_counts;
01333         if ( m_start_ptrs ) delete [] m_start_ptrs;
01334         if ( m_covers ) delete [] m_covers;
01335     }
01336 
01337 
01338     //------------------------------------------------------------------------
01339     scanline::scanline()
01340         : m_min_x(0),
01341           m_max_len(0),
01342           m_dx(0),
01343           m_dy(0),
01344           m_last_x(0x7FFF),
01345           m_last_y(0x7FFF),
01346           m_covers(0),
01347           m_start_ptrs(0),
01348           m_counts(0),
01349           m_num_spans(0),
01350           m_cur_start_ptr(0),
01351           m_cur_count(0)
01352     {
01353     }
01354 
01355 
01356     //------------------------------------------------------------------------
01357     void scanline::reset(int min_x, int max_x, int dx, int dy)
01358     {
01359         unsigned max_len = max_x - min_x + 2;
01360         if(max_len > m_max_len)
01361         {
01362             if ( m_counts ) delete [] m_counts;
01363             if ( m_start_ptrs ) delete [] m_start_ptrs;
01364             if ( m_covers ) delete [] m_covers;
01365             m_covers     = new unsigned char  [max_len];
01366             m_start_ptrs = new unsigned char* [max_len];
01367             m_counts     = new int16u[max_len];
01368             m_max_len    = max_len;
01369         }
01370         m_dx            = dx;
01371         m_dy            = dy;
01372         m_last_x        = 0x7FFF;
01373         m_last_y        = 0x7FFF;
01374         m_min_x         = min_x;
01375         m_cur_count     = m_counts;
01376         m_cur_start_ptr = m_start_ptrs;
01377         m_num_spans     = 0;
01378     }
01379 
01380 
01381     //------------------------------------------------------------------------
01382     void scanline::add_span(int x, int y, unsigned num, unsigned cover)
01383     {
01384         x -= m_min_x;
01385 
01386         memset(m_covers + x, cover, num);
01387         if(x == m_last_x+1)
01388         {
01389             (*m_cur_count) += (int16u)num;
01390         }
01391         else
01392         {
01393             *++m_cur_count = (int16u)num;
01394             *++m_cur_start_ptr = m_covers + x;
01395             m_num_spans++;
01396         }
01397         m_last_x = x + num - 1;
01398         m_last_y = y;
01399     }
01400 
01401 
01402 
01403     //========================================================================
01404 
01405     //------------------------------------------------------------------------
01406     const int8u rasterizer::s_default_gamma[] = 
01407     {
01408           0,  0,  1,  1,  2,  2,  3,  4,  4,  5,  5,  6,  7,  7,  8,  8,
01409           9, 10, 10, 11, 11, 12, 13, 13, 14, 14, 15, 16, 16, 17, 18, 18,
01410          19, 19, 20, 21, 21, 22, 22, 23, 24, 24, 25, 25, 26, 27, 27, 28,
01411          29, 29, 30, 30, 31, 32, 32, 33, 34, 34, 35, 36, 36, 37, 37, 38,
01412          39, 39, 40, 41, 41, 42, 43, 43, 44, 45, 45, 46, 47, 47, 48, 49,
01413          49, 50, 51, 51, 52, 53, 53, 54, 55, 55, 56, 57, 57, 58, 59, 60,
01414          60, 61, 62, 62, 63, 64, 65, 65, 66, 67, 68, 68, 69, 70, 71, 71,
01415          72, 73, 74, 74, 75, 76, 77, 78, 78, 79, 80, 81, 82, 83, 83, 84,
01416          85, 86, 87, 88, 89, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
01417         100,101,101,102,103,104,105,106,107,108,109,110,111,112,114,115,
01418         116,117,118,119,120,121,122,123,124,126,127,128,129,130,131,132,
01419         134,135,136,137,139,140,141,142,144,145,146,147,149,150,151,153,
01420         154,155,157,158,159,161,162,164,165,166,168,169,171,172,174,175,
01421         177,178,180,181,183,184,186,188,189,191,192,194,195,197,199,200,
01422         202,204,205,207,209,210,212,214,215,217,219,220,222,224,225,227,
01423         229,230,232,234,236,237,239,241,242,244,246,248,249,251,253,255
01424     };
01425 
01426 
01427 
01428 
01429 
01430     //========================================================================
01431     enum
01432     {
01433         not_closed    = 1,
01434         sort_required = 2
01435     };
01436 
01437     //------------------------------------------------------------------------
01438     inline void cell::set_cover(int c, int a)
01439     {
01440         cover = c;
01441         area = a;
01442     }
01443 
01444     //------------------------------------------------------------------------
01445     inline void cell::add_cover(int c, int a)
01446     {
01447         cover += c;
01448         area += a;
01449     }
01450 
01451     //------------------------------------------------------------------------
01452     inline void cell::set_coord(int cx, int cy)
01453     {
01454         x = int16(cx);
01455         y = int16(cy);
01456         packed_coord = (cy << 16) + cx;
01457     }
01458 
01459     //------------------------------------------------------------------------
01460     inline void cell::set(int cx, int cy, int c, int a)
01461     {
01462         x = int16(cx);
01463         y = int16(cy);
01464         packed_coord = (cy << 16) + cx;
01465         cover = c;
01466         area = a;
01467     }
01468 
01469     //------------------------------------------------------------------------
01470     outline::~outline()
01471     {
01472         delete [] m_sorted_cells;
01473         if(m_num_blocks)
01474         {
01475             cell** ptr = m_cells + m_num_blocks - 1;
01476             while(m_num_blocks--)
01477             {
01478                 delete [] *ptr;
01479                 ptr--;
01480             }
01481             delete [] m_cells;
01482         }
01483     }
01484 
01485 
01486     //------------------------------------------------------------------------
01487     outline::outline() :
01488         m_num_blocks(0),
01489         m_max_blocks(0),
01490         m_cur_block(0),
01491         m_num_cells(0),
01492         m_cells(0),
01493         m_cur_cell_ptr(0),
01494         m_sorted_cells(0),
01495         m_sorted_size(0),
01496         m_cur_x(0),
01497         m_cur_y(0),
01498         m_close_x(0),
01499         m_close_y(0),
01500         m_min_x(0x7FFFFFFF),
01501         m_min_y(0x7FFFFFFF),
01502         m_max_x(-0x7FFFFFFF),
01503         m_max_y(-0x7FFFFFFF),
01504         m_flags(sort_required)
01505     {
01506         m_cur_cell.set(0x7FFF, 0x7FFF, 0, 0);
01507     }
01508 
01509 
01510     //------------------------------------------------------------------------
01511     void outline::reset()
01512     { 
01513         m_num_cells = 0; 
01514         m_cur_block = 0;
01515         m_cur_cell.set(0x7FFF, 0x7FFF, 0, 0);
01516         m_flags |= sort_required;
01517         m_flags &= ~not_closed;
01518         m_min_x =  0x7FFFFFFF;
01519         m_min_y =  0x7FFFFFFF;
01520         m_max_x = -0x7FFFFFFF;
01521         m_max_y = -0x7FFFFFFF;
01522     }
01523 
01524 
01525 
01526     //------------------------------------------------------------------------
01527     void outline::allocate_block()
01528     {
01529         if(m_cur_block >= m_num_blocks)
01530         {
01531             if(m_num_blocks >= m_max_blocks)
01532             {
01533                 cell** new_cells = new cell* [m_max_blocks + cell_block_pool];
01534                 if(m_cells)
01535                 {
01536                     memcpy(new_cells, m_cells, m_max_blocks * sizeof(cell*));
01537                     delete [] m_cells;
01538                 }
01539                 m_cells = new_cells;
01540                 m_max_blocks += cell_block_pool;
01541             }
01542             m_cells[m_num_blocks++] = new cell [unsigned(cell_block_size)];
01543         }
01544         m_cur_cell_ptr = m_cells[m_cur_block++];
01545     }
01546 
01547 
01548     //------------------------------------------------------------------------
01549     inline void outline::add_cur_cell()
01550     {
01551         if(m_cur_cell.area | m_cur_cell.cover)
01552         {
01553             if((m_num_cells & cell_block_mask) == 0)
01554             {
01555                 if(m_num_blocks >= cell_block_limit) return;
01556                 allocate_block();
01557             }
01558             *m_cur_cell_ptr++ = m_cur_cell;
01559             m_num_cells++;
01560         }
01561     }
01562 
01563 
01564 
01565     //------------------------------------------------------------------------
01566     inline void outline::set_cur_cell(int x, int y)
01567     {
01568         if(m_cur_cell.packed_coord != (y << 16) + x)
01569         {
01570             add_cur_cell();
01571             m_cur_cell.set(x, y, 0, 0);
01572         }
01573     }
01574 
01575 
01576 
01577     //------------------------------------------------------------------------
01578     inline void outline::render_scanline(int ey, int x1, int y1, int x2, int y2)
01579     {
01580         int ex1 = x1 >> poly_base_shift;
01581         int ex2 = x2 >> poly_base_shift;
01582         int fx1 = x1 & poly_base_mask;
01583         int fx2 = x2 & poly_base_mask;
01584 
01585         int delta, p, first, dx;
01586         int incr, lift, mod, rem;
01587 
01588         //trivial case. Happens often
01589         if(y1 == y2)
01590         {
01591             set_cur_cell(ex2, ey);
01592             return;
01593         }
01594 
01595         //everything is located in a single cell.  That is easy!
01596         if(ex1 == ex2)
01597         {
01598             delta = y2 - y1;
01599             m_cur_cell.add_cover(delta, (fx1 + fx2) * delta);
01600             return;
01601         }
01602 
01603         //ok, we'll have to render a run of adjacent cells on the same
01604         //scanline...
01605         p     = (poly_base_size - fx1) * (y2 - y1);
01606         first = poly_base_size;
01607         incr  = 1;
01608 
01609         dx = x2 - x1;
01610 
01611         if(dx < 0)
01612         {
01613             p     = fx1 * (y2 - y1);
01614             first = 0;
01615             incr  = -1;
01616             dx    = -dx;
01617         }
01618 
01619         delta = p / dx;
01620         mod   = p % dx;
01621 
01622         if(mod < 0)
01623         {
01624             delta--;
01625             mod += dx;
01626         }
01627 
01628         m_cur_cell.add_cover(delta, (fx1 + first) * delta);
01629 
01630         ex1 += incr;
01631         set_cur_cell(ex1, ey);
01632         y1  += delta;
01633 
01634         if(ex1 != ex2)
01635         {
01636             p     = poly_base_size * (y2 - y1 + delta);
01637             lift  = p / dx;
01638             rem   = p % dx;
01639 
01640             if (rem < 0)
01641             {
01642                 lift--;
01643                 rem += dx;
01644             }
01645 
01646             mod -= dx;
01647 
01648             while (ex1 != ex2)
01649             {
01650                 delta = lift;
01651                 mod  += rem;
01652                 if(mod >= 0)
01653                 {
01654                     mod -= dx;
01655                     delta++;
01656                 }
01657 
01658                 m_cur_cell.add_cover(delta, (poly_base_size) * delta);
01659                 y1  += delta;
01660                 ex1 += incr;
01661                 set_cur_cell(ex1, ey);
01662             }
01663         }
01664         delta = y2 - y1;
01665         m_cur_cell.add_cover(delta, (fx2 + poly_base_size - first) * delta);
01666     }
01667 
01668 
01669 
01670 
01671 
01672 
01673     //------------------------------------------------------------------------
01674     void outline::render_line(int x1, int y1, int x2, int y2)
01675     {
01676         int ey1 = y1 >> poly_base_shift;
01677         int ey2 = y2 >> poly_base_shift;
01678         int fy1 = y1 & poly_base_mask;
01679         int fy2 = y2 & poly_base_mask;
01680 
01681         int dx, dy, x_from, x_to;
01682         int p, rem, mod, lift, delta, first, incr;
01683 
01684         if(ey1   < m_min_y) m_min_y = ey1;
01685         if(ey1+1 > m_max_y) m_max_y = ey1+1;
01686         if(ey2   < m_min_y) m_min_y = ey2;
01687         if(ey2+1 > m_max_y) m_max_y = ey2+1;
01688 
01689         dx = x2 - x1;
01690         dy = y2 - y1;
01691 
01692         //everything is on a single scanline
01693         if(ey1 == ey2)
01694         {
01695             render_scanline(ey1, x1, fy1, x2, fy2);
01696             return;
01697         }
01698 
01699         //Vertical line - we have to calculate start and end cells,
01700         //and then - the common values of the area and coverage for
01701         //all cells of the line. We know exactly there's only one 
01702         //cell, so, we don't have to call render_scanline().
01703         incr  = 1;
01704         if(dx == 0)
01705         {
01706             int ex = x1 >> poly_base_shift;
01707             int two_fx = (x1 - (ex << poly_base_shift)) << 1;
01708             int area;
01709 
01710             first = poly_base_size;
01711             if(dy < 0)
01712             {
01713                 first = 0;
01714                 incr  = -1;
01715             }
01716 
01717             x_from = x1;
01718 
01719             //render_scanline(ey1, x_from, fy1, x_from, first);
01720             delta = first - fy1;
01721             m_cur_cell.add_cover(delta, two_fx * delta);
01722 
01723             ey1 += incr;
01724             set_cur_cell(ex, ey1);
01725 
01726             delta = first + first - poly_base_size;
01727             area = two_fx * delta;
01728             while(ey1 != ey2)
01729             {
01730                 //render_scanline(ey1, x_from, poly_base_size - first, x_from, first);
01731                 m_cur_cell.set_cover(delta, area);
01732                 ey1 += incr;
01733                 set_cur_cell(ex, ey1);
01734             }
01735             //render_scanline(ey1, x_from, poly_base_size - first, x_from, fy2);
01736             delta = fy2 - poly_base_size + first;
01737             m_cur_cell.add_cover(delta, two_fx * delta);
01738             return;
01739         }
01740 
01741         //ok, we have to render several scanlines
01742         p     = (poly_base_size - fy1) * dx;
01743         first = poly_base_size;
01744 
01745         if(dy < 0)
01746         {
01747             p     = fy1 * dx;
01748             first = 0;
01749             incr  = -1;
01750             dy    = -dy;
01751         }
01752 
01753         delta = p / dy;
01754         mod   = p % dy;
01755 
01756         if(mod < 0)
01757         {
01758             delta--;
01759             mod += dy;
01760         }
01761 
01762         x_from = x1 + delta;
01763         render_scanline(ey1, x1, fy1, x_from, first);
01764 
01765         ey1 += incr;
01766         set_cur_cell(x_from >> poly_base_shift, ey1);
01767 
01768         if(ey1 != ey2)
01769         {
01770             p     = poly_base_size * dx;
01771             lift  = p / dy;
01772             rem   = p % dy;
01773 
01774             if(rem < 0)
01775             {
01776                 lift--;
01777                 rem += dy;
01778             }
01779             mod -= dy;
01780 
01781             while(ey1 != ey2)
01782             {
01783                 delta = lift;
01784                 mod  += rem;
01785                 if (mod >= 0)
01786                 {
01787                     mod -= dy;
01788                     delta++;
01789                 }
01790 
01791                 x_to = x_from + delta;
01792                 render_scanline(ey1, x_from, poly_base_size - first, x_to, first);
01793                 x_from = x_to;
01794 
01795                 ey1 += incr;
01796                 set_cur_cell(x_from >> poly_base_shift, ey1);
01797             }
01798         }
01799         render_scanline(ey1, x_from, poly_base_size - first, x2, fy2);
01800     }
01801 
01802 
01803     //------------------------------------------------------------------------
01804     void outline::move_to(int x, int y)
01805     {
01806         if((m_flags & sort_required) == 0) reset();
01807         if(m_flags & not_closed) line_to(m_close_x, m_close_y);
01808         set_cur_cell(x >> poly_base_shift, y >> poly_base_shift);
01809         m_close_x = m_cur_x = x;
01810         m_close_y = m_cur_y = y;
01811     }
01812 
01813 
01814 
01815     //------------------------------------------------------------------------
01816     void outline::line_to(int x, int y)
01817     {
01818         if((m_flags & sort_required) && ((m_cur_x ^ x) | (m_cur_y ^ y)))
01819         {
01820             int c;
01821 
01822             c = m_cur_x >> poly_base_shift;
01823             if(c < m_min_x) m_min_x = c;
01824             ++c;
01825             if(c > m_max_x) m_max_x = c;
01826 
01827             c = x >> poly_base_shift;
01828             if(c < m_min_x) m_min_x = c;
01829             ++c;
01830             if(c > m_max_x) m_max_x = c;
01831 
01832             render_line(m_cur_x, m_cur_y, x, y);
01833             m_cur_x = x;
01834             m_cur_y = y;
01835             m_flags |= not_closed;
01836         }
01837     }
01838 
01839 
01840     enum
01841     {
01842         qsort_threshold = 9
01843     };
01844 
01845 
01846     //------------------------------------------------------------------------
01847     template <class T> static inline void swap_cells(T* a, T* b)
01848     {
01849         T temp = *a;
01850         *a = *b;
01851         *b = temp;
01852     }
01853 
01854     //------------------------------------------------------------------------
01855     template <class T> static inline bool less_than(T* a, T* b)
01856     {
01857         return (*a)->packed_coord < (*b)->packed_coord;
01858     }
01859 
01860 
01861 
01862     //------------------------------------------------------------------------
01863     void outline::qsort_cells(cell** start, unsigned num)
01864     {
01865         cell**  stack[80];
01866         cell*** top; 
01867         cell**  limit;
01868         cell**  base;
01869 
01870         limit = start + num;
01871         base  = start;
01872         top   = stack;
01873 
01874         for (;;)
01875         {
01876             int len = int(limit - base);
01877 
01878             cell** i;
01879             cell** j;
01880             cell** pivot;
01881 
01882             if(len > qsort_threshold)
01883             {
01884                 // we use base + len/2 as the pivot
01885                 pivot = base + len / 2;
01886                 swap_cells(base, pivot);
01887 
01888                 i = base + 1;
01889                 j = limit - 1;
01890 
01891                 // now ensure that *i <= *base <= *j 
01892                 if(less_than(j, i))
01893                 {
01894                     swap_cells(i, j);
01895                 }
01896 
01897                 if(less_than(base, i))
01898                 {
01899                     swap_cells(base, i);
01900                 }
01901 
01902                 if(less_than(j, base))
01903                 {
01904                     swap_cells(base, j);
01905                 }
01906 
01907                 for(;;)
01908                 {
01909                     do i++; while( less_than(i, base) );
01910                     do j--; while( less_than(base, j) );
01911 
01912                     if ( i > j )
01913                     {
01914                         break;
01915                     }
01916 
01917                     swap_cells(i, j);
01918                 }
01919 
01920                 swap_cells(base, j);
01921 
01922                 // now, push the largest sub-array
01923                 if(j - base > limit - i)
01924                 {
01925                     top[0] = base;
01926                     top[1] = j;
01927                     base   = i;
01928                 }
01929                 else
01930                 {
01931                     top[0] = i;
01932                     top[1] = limit;
01933                     limit  = j;
01934                 }
01935                 top += 2;
01936             }
01937             else
01938             {
01939                 // the sub-array is small, perform insertion sort
01940                 j = base;
01941                 i = j + 1;
01942 
01943                 for(; i < limit; j = i, i++)
01944                 {
01945                     for(; less_than(j + 1, j); j--)
01946                     {
01947                         swap_cells(j + 1, j);
01948                         if (j == base)
01949                         {
01950                             break;
01951                         }
01952                     }
01953                 }
01954                 if(top > stack)
01955                 {
01956                     top  -= 2;
01957                     base  = top[0];
01958                     limit = top[1];
01959                 }
01960                 else
01961                 {
01962                     break;
01963                 }
01964             }
01965         }
01966     }
01967 
01968 
01969 
01970 
01971 
01972     //------------------------------------------------------------------------
01973     void outline::sort_cells()
01974     {
01975         if(m_num_cells == 0) return;
01976         if(m_num_cells > m_sorted_size)
01977         {
01978             delete [] m_sorted_cells;
01979             m_sorted_size = m_num_cells;
01980             m_sorted_cells = new cell* [m_num_cells + 1];
01981         }
01982 
01983         cell** sorted_ptr = m_sorted_cells;
01984         cell** block_ptr = m_cells;
01985         cell*  cell_ptr;
01986 
01987         unsigned nb = m_num_cells >> cell_block_shift;
01988         unsigned i;
01989 
01990         while(nb--)
01991         {
01992             cell_ptr = *block_ptr++;
01993             i = cell_block_size;
01994             while(i--) 
01995             {
01996                 *sorted_ptr++ = cell_ptr++;
01997             }
01998         }
01999 
02000         cell_ptr = *block_ptr++;
02001         i = m_num_cells & cell_block_mask;
02002         while(i--) 
02003         {
02004             *sorted_ptr++ = cell_ptr++;
02005         }
02006         m_sorted_cells[m_num_cells] = 0;
02007         qsort_cells(m_sorted_cells, m_num_cells);
02008     }
02009 
02010 
02011 
02012 
02013     //------------------------------------------------------------------------
02014     const cell* const* outline::cells()
02015     {
02016         if(m_flags & not_closed)
02017         {
02018             line_to(m_close_x, m_close_y);
02019             m_flags &= ~not_closed;
02020         }
02021 
02022         //Perform sort only the first time.
02023         if(m_flags & sort_required)
02024         {
02025             add_cur_cell();
02026             if(m_num_cells == 0) return 0;
02027             sort_cells();
02028             m_flags &= ~sort_required;
02029         }
02030         return m_sorted_cells;
02031     }
02032 
02033 
02034 
02035     //------------------------------------------------------------------------
02036     void rasterizer::gamma(double g)
02037     {
02038         unsigned i;
02039         for(i = 0; i < 256; i++)
02040         {
02041             m_gamma[i] = (unsigned char)(pow(double(i) / 255.0, g) * 255.0);
02042         }
02043     }
02044 
02045 
02046     //------------------------------------------------------------------------
02047     void rasterizer::gamma(const int8u* g)
02048     {
02049         memcpy(m_gamma, g, sizeof(m_gamma));
02050     }
02051 
02052 
02053     //------------------------------------------------------------------------
02054     bool rasterizer::hit_test(int tx, int ty)
02055     {
02056         const cell* const* cells = m_outline.cells();
02057         if(m_outline.num_cells() == 0) return false;
02058 
02059         int x, y;
02060         int cover;
02061         int alpha;
02062         int area;
02063 
02064         cover = 0;
02065         const cell* cur_cell = *cells++;
02066         for(;;)
02067         {
02068             const cell* start_cell = cur_cell;
02069 
02070             int coord  = cur_cell->packed_coord;
02071             x = cur_cell->x;
02072             y = cur_cell->y;
02073 
02074             if(y > ty) return false;
02075 
02076             area   = start_cell->area;
02077             cover += start_cell->cover;
02078 
02079             while((cur_cell = *cells++) != 0)
02080             {
02081                 if(cur_cell->packed_coord != coord) break;
02082                 area  += cur_cell->area;
02083                 cover += cur_cell->cover;
02084             }
02085 
02086             if(area)
02087             {
02088                 alpha = calculate_alpha((cover << (poly_base_shift + 1)) - area);
02089                 if(alpha)
02090                 {
02091                     if(tx == x && ty == y) return true;
02092                 }
02093                 x++;
02094             }
02095 
02096             if(!cur_cell) break;
02097 
02098             if(cur_cell->x > x)
02099             {
02100                 alpha = calculate_alpha(cover << (poly_base_shift + 1));
02101                 if(alpha)
02102                 {
02103                     if(ty == y && tx >= x && tx <= cur_cell->x) return true;
02104                 }
02105             }
02106         }
02107         return false;
02108     }
02109 }
02110 
02111 #endif // AGGLITE_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines