Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | Related Pages | Examples

agg_scanline_u.h

00001 //----------------------------------------------------------------------------
00002 // Anti-Grain Geometry - Version 2.2
00003 // Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
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 //----------------------------------------------------------------------------
00011 // Contact: mcseem@antigrain.com
00012 //          mcseemagg@yahoo.com
00013 //          http://www.antigrain.com
00014 //----------------------------------------------------------------------------
00015 
00016 #ifndef AGG_SCANLINE_U_INCLUDED
00017 #define AGG_SCANLINE_U_INCLUDED
00018 
00019 #include <string.h>
00020 #include "agg_basics.h"
00021 
00022 namespace agg
00023 {
00024     //==============================================================scanline_u
00025     //
00026     // Unpacked scanline container class
00027     //
00028     // This class is used to transfer data from a scanline rastyerizer 
00029     // to the rendering buffer. It's organized very simple. The class stores 
00030     // information of horizontal spans to render it into a pixel-map buffer. 
00031     // Each span has staring X, length, and an array of bytes that determine the 
00032     // cover-values for each pixel. 
00033     // Before using this class you should know the minimal and maximal pixel 
00034     // coordinates of your scanline. The protocol of using is:
00035     // 1. reset(min_x, max_x)
00036     // 2. add_cell() / add_span() - accumulate scanline. 
00037     //    When forming one scanline the next X coordinate must be always greater
00038     //    than the last stored one, i.e. it works only with ordered coordinates.
00039     // 3. Call finalize(y) and render the scanline.
00040     // 3. Call reset_spans() to prepare for the new scanline.
00041     //    
00042     // 4. Rendering:
00043     // 
00044     // Scanline provides an iterator class that allows you to extract
00045     // the spans and the cover values for each pixel. Be aware that clipping
00046     // has not been done yet, so you should perform it yourself.
00047     // Use scanline_u8::iterator to render spans:
00048     //-------------------------------------------------------------------------
00049     //
00050     // int y = sl.y();                    // Y-coordinate of the scanline
00051     //
00052     // ************************************
00053     // ...Perform vertical clipping here...
00054     // ************************************
00055     //
00056     // scanline_u8::const_iterator span = sl.begin();
00057     // 
00058     // unsigned char* row = m_rbuf->row(y); // The the address of the beginning 
00059     //                                      // of the current row
00060     // 
00061     // unsigned num_spans = sl.num_spans(); // Number of spans. It's guaranteed that
00062     //                                      // num_spans is always greater than 0.
00063     //
00064     // do
00065     // {
00066     //     const scanline_u8::cover_type* covers =
00067     //         span->covers;                     // The array of the cover values
00068     //
00069     //     int num_pix = span->len;              // Number of pixels of the span.
00070     //                                           // Always greater than 0, still it's
00071     //                                           // better to use "int" instead of 
00072     //                                           // "unsigned" because it's more
00073     //                                           // convenient for clipping
00074     //     int x = span->x;
00075     //
00076     //     **************************************
00077     //     ...Perform horizontal clipping here...
00078     //     ...you have x, covers, and pix_count..
00079     //     **************************************
00080     //
00081     //     unsigned char* dst = row + x;  // Calculate the start address of the row.
00082     //                                    // In this case we assume a simple 
00083     //                                    // grayscale image 1-byte per pixel.
00084     //     do
00085     //     {
00086     //         *dst++ = *covers++;        // Hypotetical rendering. 
00087     //     }
00088     //     while(--num_pix);
00089     //
00090     //     ++span;
00091     // } 
00092     // while(--num_spans);  // num_spans cannot be 0, so this loop is quite safe
00093     //------------------------------------------------------------------------
00094     //
00095     // The question is: why should we accumulate the whole scanline when we
00096     // could render just separate spans when they're ready?
00097     // That's because using the scaline is generally faster. When is consists 
00098     // of more than one span the conditions for the processor cash system
00099     // are better, because switching between two different areas of memory 
00100     // (that can be very large) occures less frequently.
00101     //------------------------------------------------------------------------
00102     template<class T> class scanline_u
00103     {
00104     public:
00105         typedef T cover_type;
00106 
00107         //--------------------------------------------------------------------
00108         struct span
00109         {
00110             int16 x;
00111             int16 len;
00112             cover_type* covers;
00113         };
00114 
00115         typedef span* iterator;
00116         typedef const span* const_iterator;
00117 
00118         //--------------------------------------------------------------------
00119         ~scanline_u();
00120         scanline_u();
00121 
00122         void     reset(int min_x, int max_x);
00123         void     add_cell(int x, unsigned cover);
00124         void     add_cells(int x, unsigned len, const T* covers);
00125         void     add_span(int x, unsigned len, unsigned cover);
00126         void     finalize(int y) { m_y = y; }
00127         void     reset_spans();
00128 
00129         int      y()           const { return m_y; }
00130         unsigned num_spans()   const { return unsigned(m_cur_span - m_spans); }
00131         const_iterator begin() const { return m_spans + 1; }
00132         iterator       begin()       { return m_spans + 1; }
00133 
00134     private:
00135         scanline_u<T>(const scanline_u<T>&);
00136         const scanline_u<T>& operator = (const scanline_u<T>&);
00137 
00138     private:
00139         int           m_min_x;
00140         unsigned      m_max_len;
00141         int           m_last_x;
00142         int           m_y;
00143         cover_type*   m_covers;
00144         span*         m_spans;
00145         span*         m_cur_span;
00146     };
00147 
00148 
00149 
00150     //------------------------------------------------------------------------
00151     template<class T> scanline_u<T>::~scanline_u()
00152     {
00153         delete [] m_spans;
00154         delete [] m_covers;
00155     }
00156 
00157 
00158     //------------------------------------------------------------------------
00159     template<class T> scanline_u<T>::scanline_u() :
00160         m_min_x(0),
00161         m_max_len(0),
00162         m_last_x(0x7FFFFFF0),
00163         m_covers(0),
00164         m_spans(0),
00165         m_cur_span(0)
00166     {
00167     }
00168 
00169 
00170     //------------------------------------------------------------------------
00171     template<class T> void scanline_u<T>::reset(int min_x, int max_x)
00172     {
00173         unsigned max_len = max_x - min_x + 2;
00174         if(max_len > m_max_len)
00175         {
00176             delete [] m_spans;
00177             delete [] m_covers;
00178             m_covers  = new cover_type [max_len];
00179             m_spans   = new span       [max_len];
00180             m_max_len = max_len;
00181         }
00182         m_last_x        = 0x7FFFFFF0;
00183         m_min_x         = min_x;
00184         m_cur_span      = m_spans;
00185     }
00186 
00187 
00188     //------------------------------------------------------------------------
00189     template<class T> inline void scanline_u<T>::reset_spans()
00190     {
00191         m_last_x    = 0x7FFFFFF0;
00192         m_cur_span  = m_spans;
00193     }
00194 
00195 
00196     //------------------------------------------------------------------------
00197     template<class T> inline void scanline_u<T>::add_cell(int x, unsigned cover)
00198     {
00199         x -= m_min_x;
00200         m_covers[x] = (unsigned char)cover;
00201         if(x == m_last_x+1)
00202         {
00203             m_cur_span->len++;
00204         }
00205         else
00206         {
00207             m_cur_span++;
00208             m_cur_span->x      = (int16)(x + m_min_x);
00209             m_cur_span->len    = 1;
00210             m_cur_span->covers = m_covers + x;
00211         }
00212         m_last_x = x;
00213     }
00214 
00215 
00216     //------------------------------------------------------------------------
00217     template<class T> void scanline_u<T>::add_cells(int x, unsigned len, const T* covers)
00218     {
00219         x -= m_min_x;
00220         memcpy(m_covers + x, covers, len * sizeof(T));
00221         if(x == m_last_x+1)
00222         {
00223             m_cur_span->len += (int16)len;
00224         }
00225         else
00226         {
00227             m_cur_span++;
00228             m_cur_span->x      = (int16)(x + m_min_x);
00229             m_cur_span->len    = (int16)len;
00230             m_cur_span->covers = m_covers + x;
00231         }
00232         m_last_x = x + len - 1;
00233     }
00234 
00235 
00236     //------------------------------------------------------------------------
00237     template<class T> void scanline_u<T>::add_span(int x, unsigned len, unsigned cover)
00238     {
00239         x -= m_min_x;
00240         memset(m_covers + x, cover, len);
00241         if(x == m_last_x+1)
00242         {
00243             m_cur_span->len += (int16)len;
00244         }
00245         else
00246         {
00247             m_cur_span++;
00248             m_cur_span->x      = (int16)(x + m_min_x);
00249             m_cur_span->len    = (int16)len;
00250             m_cur_span->covers = m_covers + x;
00251         }
00252         m_last_x = x + len - 1;
00253     }
00254 
00255 
00256     //=============================================================scanline_u8
00257     typedef scanline_u<int8u> scanline_u8;
00258 
00259     //============================================================scanline_u16
00260     typedef scanline_u<int16u> scanline_u16;
00261 
00262     //============================================================scanline_u32
00263     typedef scanline_u<int32u> scanline_u32;
00264 
00265 
00266     //=============================================================scanline_am
00267     // 
00268     // The scanline container with alpha-masking
00269     // 
00270     //------------------------------------------------------------------------
00271     template<class AlphaMask, class CoverT> 
00272     class scanline_am : public scanline_u<CoverT>
00273     {
00274     public:
00275         typedef AlphaMask alpha_mask_type;
00276         typedef CoverT cover_type;
00277         typedef scanline_u<CoverT> scanline_type;
00278 
00279         scanline_am() : scanline_type(), m_alpha_mask(0) {}
00280         scanline_am(const AlphaMask& am) : scanline_type(), m_alpha_mask(&am) {}
00281 
00282         //--------------------------------------------------------------------
00283         void finalize(int span_y)
00284         {
00285             scanline_u<CoverT>::finalize(span_y);
00286             if(m_alpha_mask)
00287             {
00288                 typename scanline_type::iterator span = scanline_type::begin();
00289                 unsigned count = scanline_type::num_spans();
00290                 do
00291                 {
00292                     m_alpha_mask->combine_hspan(span->x, 
00293                                                 scanline_type::y(), 
00294                                                 span->covers, 
00295                                                 span->len);
00296                     ++span;
00297                 }
00298                 while(--count);
00299             }
00300         }
00301 
00302     private:
00303         const AlphaMask* m_alpha_mask;
00304     };
00305 
00306 
00307     //==========================================================scanline_u8_am
00308     template<class AlphaMask> 
00309     class scanline_u8_am : public scanline_am<AlphaMask, int8u>
00310     {
00311     public:
00312         typedef AlphaMask alpha_mask_type;
00313         typedef int8u cover_type;
00314         typedef scanline_am<alpha_mask_type, cover_type> self_type;
00315 
00316         scanline_u8_am() : self_type() {}
00317         scanline_u8_am(const AlphaMask& am) : self_type(am) {}
00318     };
00319 
00320 }
00321 
00322 #endif
00323 

Generated on Wed Feb 9 11:31:35 2005 for OpenGUI by  doxygen 1.4.0