Anti-Grain Geometry - AGG (libagg)  2.5
agg-2.5/include/agg_scanline_u.h
Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 // Anti-Grain Geometry (AGG) - Version 2.5
00003 // A high quality rendering engine for C++
00004 // Copyright (C) 2002-2006 Maxim Shemanarev
00005 // Contact: mcseem@antigrain.com
00006 //          mcseemagg@yahoo.com
00007 //          http://antigrain.com
00008 // 
00009 // AGG is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU General Public License
00011 // as published by the Free Software Foundation; either version 2
00012 // of the License, or (at your option) any later version.
00013 // 
00014 // AGG is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 // GNU General Public License for more details.
00018 // 
00019 // You should have received a copy of the GNU General Public License
00020 // along with AGG; if not, write to the Free Software
00021 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
00022 // MA 02110-1301, USA.
00023 //----------------------------------------------------------------------------
00024 //
00025 // Adaptation for 32-bit screen coordinates (scanline32_u) has been sponsored by 
00026 // Liberty Technology Systems, Inc., visit http://lib-sys.com
00027 //
00028 // Liberty Technology Systems, Inc. is the provider of
00029 // PostScript and PDF technology for software developers.
00030 // 
00031 //----------------------------------------------------------------------------
00032 
00033 #ifndef AGG_SCANLINE_U_INCLUDED
00034 #define AGG_SCANLINE_U_INCLUDED
00035 
00036 #include "agg_array.h"
00037 
00038 namespace agg
00039 {
00040     //=============================================================scanline_u8
00041     //
00042     // Unpacked scanline container class
00043     //
00044     // This class is used to transfer data from a scanline rasterizer 
00045     // to the rendering buffer. It's organized very simple. The class stores 
00046     // information of horizontal spans to render it into a pixel-map buffer. 
00047     // Each span has staring X, length, and an array of bytes that determine the 
00048     // cover-values for each pixel. 
00049     // Before using this class you should know the minimal and maximal pixel 
00050     // coordinates of your scanline. The protocol of using is:
00051     // 1. reset(min_x, max_x)
00052     // 2. add_cell() / add_span() - accumulate scanline. 
00053     //    When forming one scanline the next X coordinate must be always greater
00054     //    than the last stored one, i.e. it works only with ordered coordinates.
00055     // 3. Call finalize(y) and render the scanline.
00056     // 3. Call reset_spans() to prepare for the new scanline.
00057     //    
00058     // 4. Rendering:
00059     // 
00060     // Scanline provides an iterator class that allows you to extract
00061     // the spans and the cover values for each pixel. Be aware that clipping
00062     // has not been done yet, so you should perform it yourself.
00063     // Use scanline_u8::iterator to render spans:
00064     //-------------------------------------------------------------------------
00065     //
00066     // int y = sl.y();                    // Y-coordinate of the scanline
00067     //
00068     // ************************************
00069     // ...Perform vertical clipping here...
00070     // ************************************
00071     //
00072     // scanline_u8::const_iterator span = sl.begin();
00073     // 
00074     // unsigned char* row = m_rbuf->row(y); // The the address of the beginning 
00075     //                                      // of the current row
00076     // 
00077     // unsigned num_spans = sl.num_spans(); // Number of spans. It's guaranteed that
00078     //                                      // num_spans is always greater than 0.
00079     //
00080     // do
00081     // {
00082     //     const scanline_u8::cover_type* covers =
00083     //         span->covers;                     // The array of the cover values
00084     //
00085     //     int num_pix = span->len;              // Number of pixels of the span.
00086     //                                           // Always greater than 0, still it's
00087     //                                           // better to use "int" instead of 
00088     //                                           // "unsigned" because it's more
00089     //                                           // convenient for clipping
00090     //     int x = span->x;
00091     //
00092     //     **************************************
00093     //     ...Perform horizontal clipping here...
00094     //     ...you have x, covers, and pix_count..
00095     //     **************************************
00096     //
00097     //     unsigned char* dst = row + x;  // Calculate the start address of the row.
00098     //                                    // In this case we assume a simple 
00099     //                                    // grayscale image 1-byte per pixel.
00100     //     do
00101     //     {
00102     //         *dst++ = *covers++;        // Hypotetical rendering. 
00103     //     }
00104     //     while(--num_pix);
00105     //
00106     //     ++span;
00107     // } 
00108     // while(--num_spans);  // num_spans cannot be 0, so this loop is quite safe
00109     //------------------------------------------------------------------------
00110     //
00111     // The question is: why should we accumulate the whole scanline when we
00112     // could render just separate spans when they're ready?
00113     // That's because using the scanline is generally faster. When is consists 
00114     // of more than one span the conditions for the processor cash system
00115     // are better, because switching between two different areas of memory 
00116     // (that can be very large) occurs less frequently.
00117     //------------------------------------------------------------------------
00118     class scanline_u8
00119     {
00120     public:
00121         typedef scanline_u8 self_type;
00122         typedef int8u       cover_type;
00123         typedef int16       coord_type;
00124 
00125         //--------------------------------------------------------------------
00126         struct span
00127         {
00128             coord_type  x;
00129             coord_type  len;
00130             cover_type* covers;
00131         };
00132 
00133         typedef span* iterator;
00134         typedef const span* const_iterator;
00135 
00136         //--------------------------------------------------------------------
00137         scanline_u8() :
00138             m_min_x(0),
00139             m_last_x(0x7FFFFFF0),
00140             m_cur_span(0)
00141         {}
00142 
00143         //--------------------------------------------------------------------
00144         void reset(int min_x, int max_x)
00145         {
00146             unsigned max_len = max_x - min_x + 2;
00147             if(max_len > m_spans.size())
00148             {
00149                 m_spans.resize(max_len);
00150                 m_covers.resize(max_len);
00151             }
00152             m_last_x   = 0x7FFFFFF0;
00153             m_min_x    = min_x;
00154             m_cur_span = &m_spans[0];
00155         }
00156 
00157         //--------------------------------------------------------------------
00158         void add_cell(int x, unsigned cover)
00159         {
00160             x -= m_min_x;
00161             m_covers[x] = (cover_type)cover;
00162             if(x == m_last_x+1)
00163             {
00164                 m_cur_span->len++;
00165             }
00166             else
00167             {
00168                 m_cur_span++;
00169                 m_cur_span->x      = (coord_type)(x + m_min_x);
00170                 m_cur_span->len    = 1;
00171                 m_cur_span->covers = &m_covers[x];
00172             }
00173             m_last_x = x;
00174         }
00175 
00176         //--------------------------------------------------------------------
00177         void add_cells(int x, unsigned len, const cover_type* covers)
00178         {
00179             x -= m_min_x;
00180             memcpy(&m_covers[x], covers, len * sizeof(cover_type));
00181             if(x == m_last_x+1)
00182             {
00183                 m_cur_span->len += (coord_type)len;
00184             }
00185             else
00186             {
00187                 m_cur_span++;
00188                 m_cur_span->x      = (coord_type)(x + m_min_x);
00189                 m_cur_span->len    = (coord_type)len;
00190                 m_cur_span->covers = &m_covers[x];
00191             }
00192             m_last_x = x + len - 1;
00193         }
00194 
00195         //--------------------------------------------------------------------
00196         void add_span(int x, unsigned len, unsigned cover)
00197         {
00198             x -= m_min_x;
00199             memset(&m_covers[x], cover, len);
00200             if(x == m_last_x+1)
00201             {
00202                 m_cur_span->len += (coord_type)len;
00203             }
00204             else
00205             {
00206                 m_cur_span++;
00207                 m_cur_span->x      = (coord_type)(x + m_min_x);
00208                 m_cur_span->len    = (coord_type)len;
00209                 m_cur_span->covers = &m_covers[x];
00210             }
00211             m_last_x = x + len - 1;
00212         }
00213 
00214         //--------------------------------------------------------------------
00215         void finalize(int y) 
00216         { 
00217             m_y = y; 
00218         }
00219 
00220         //--------------------------------------------------------------------
00221         void reset_spans()
00222         {
00223             m_last_x    = 0x7FFFFFF0;
00224             m_cur_span  = &m_spans[0];
00225         }
00226 
00227         //--------------------------------------------------------------------
00228         int      y()           const { return m_y; }
00229         unsigned num_spans()   const { return unsigned(m_cur_span - &m_spans[0]); }
00230         const_iterator begin() const { return &m_spans[1]; }
00231         iterator       begin()       { return &m_spans[1]; }
00232 
00233     private:
00234         scanline_u8(const self_type&);
00235         const self_type& operator = (const self_type&);
00236 
00237     private:
00238         int                   m_min_x;
00239         int                   m_last_x;
00240         int                   m_y;
00241         pod_array<cover_type> m_covers;
00242         pod_array<span>       m_spans;
00243         span*                 m_cur_span;
00244     };
00245 
00246 
00247 
00248 
00249     //==========================================================scanline_u8_am
00250     // 
00251     // The scanline container with alpha-masking
00252     // 
00253     //------------------------------------------------------------------------
00254     template<class AlphaMask> 
00255     class scanline_u8_am : public scanline_u8
00256     {
00257     public:
00258         typedef scanline_u8           base_type;
00259         typedef AlphaMask             alpha_mask_type;
00260         typedef base_type::cover_type cover_type;
00261         typedef base_type::coord_type coord_type;
00262 
00263         scanline_u8_am() : base_type(), m_alpha_mask(0) {}
00264         scanline_u8_am(const AlphaMask& am) : base_type(), m_alpha_mask(&am) {}
00265 
00266         //--------------------------------------------------------------------
00267         void finalize(int span_y)
00268         {
00269             base_type::finalize(span_y);
00270             if(m_alpha_mask)
00271             {
00272                 typename base_type::iterator span = base_type::begin();
00273                 unsigned count = base_type::num_spans();
00274                 do
00275                 {
00276                     m_alpha_mask->combine_hspan(span->x, 
00277                                                 base_type::y(), 
00278                                                 span->covers, 
00279                                                 span->len);
00280                     ++span;
00281                 }
00282                 while(--count);
00283             }
00284         }
00285 
00286     private:
00287         const AlphaMask* m_alpha_mask;
00288     };
00289 
00290 
00291 
00292 
00293     //===========================================================scanline32_u8
00294     class scanline32_u8
00295     {
00296     public:
00297         typedef scanline32_u8 self_type;
00298         typedef int8u         cover_type;
00299         typedef int32         coord_type;
00300 
00301         //--------------------------------------------------------------------
00302         struct span
00303         {
00304             span() {}
00305             span(coord_type x_, coord_type len_, cover_type* covers_) :
00306                 x(x_), len(len_), covers(covers_) {}
00307 
00308             coord_type  x;
00309             coord_type  len;
00310             cover_type* covers;
00311         };
00312 
00313         typedef pod_bvector<span, 4> span_array_type;
00314 
00315         //--------------------------------------------------------------------
00316         class const_iterator
00317         {
00318         public:
00319             const_iterator(const span_array_type& spans) :
00320                 m_spans(spans),
00321                 m_span_idx(0)
00322             {}
00323 
00324             const span& operator*()  const { return m_spans[m_span_idx];  }
00325             const span* operator->() const { return &m_spans[m_span_idx]; }
00326 
00327             void operator ++ () { ++m_span_idx; }
00328 
00329         private:
00330             const span_array_type& m_spans;
00331             unsigned               m_span_idx;
00332         };
00333 
00334         //--------------------------------------------------------------------
00335         class iterator
00336         {
00337         public:
00338             iterator(span_array_type& spans) :
00339                 m_spans(spans),
00340                 m_span_idx(0)
00341             {}
00342 
00343             span& operator*()  { return m_spans[m_span_idx];  }
00344             span* operator->() { return &m_spans[m_span_idx]; }
00345 
00346             void operator ++ () { ++m_span_idx; }
00347 
00348         private:
00349             span_array_type& m_spans;
00350             unsigned         m_span_idx;
00351         };
00352 
00353 
00354 
00355         //--------------------------------------------------------------------
00356         scanline32_u8() :
00357             m_min_x(0),
00358             m_last_x(0x7FFFFFF0),
00359             m_covers()
00360         {}
00361 
00362         //--------------------------------------------------------------------
00363         void reset(int min_x, int max_x)
00364         {
00365             unsigned max_len = max_x - min_x + 2;
00366             if(max_len > m_covers.size())
00367             {
00368                 m_covers.resize(max_len);
00369             }
00370             m_last_x = 0x7FFFFFF0;
00371             m_min_x  = min_x;
00372             m_spans.remove_all();
00373         }
00374 
00375         //--------------------------------------------------------------------
00376         void add_cell(int x, unsigned cover)
00377         {
00378             x -= m_min_x;
00379             m_covers[x] = cover_type(cover);
00380             if(x == m_last_x+1)
00381             {
00382                 m_spans.last().len++;
00383             }
00384             else
00385             {
00386                 m_spans.add(span(coord_type(x + m_min_x), 1, &m_covers[x]));
00387             }
00388             m_last_x = x;
00389         }
00390 
00391         //--------------------------------------------------------------------
00392         void add_cells(int x, unsigned len, const cover_type* covers)
00393         {
00394             x -= m_min_x;
00395             memcpy(&m_covers[x], covers, len * sizeof(cover_type));
00396             if(x == m_last_x+1)
00397             {
00398                 m_spans.last().len += coord_type(len);
00399             }
00400             else
00401             {
00402                 m_spans.add(span(coord_type(x + m_min_x), 
00403                                  coord_type(len), 
00404                                  &m_covers[x]));
00405             }
00406             m_last_x = x + len - 1;
00407         }
00408 
00409         //--------------------------------------------------------------------
00410         void add_span(int x, unsigned len, unsigned cover)
00411         {
00412             x -= m_min_x;
00413             memset(&m_covers[x], cover, len);
00414             if(x == m_last_x+1)
00415             {
00416                 m_spans.last().len += coord_type(len);
00417             }
00418             else
00419             {
00420                 m_spans.add(span(coord_type(x + m_min_x), 
00421                                  coord_type(len), 
00422                                  &m_covers[x]));
00423             }
00424             m_last_x = x + len - 1;
00425         }
00426 
00427         //--------------------------------------------------------------------
00428         void finalize(int y) 
00429         { 
00430             m_y = y; 
00431         }
00432 
00433         //--------------------------------------------------------------------
00434         void reset_spans()
00435         {
00436             m_last_x = 0x7FFFFFF0;
00437             m_spans.remove_all();
00438         }
00439 
00440         //--------------------------------------------------------------------
00441         int      y()           const { return m_y; }
00442         unsigned num_spans()   const { return m_spans.size(); }
00443         const_iterator begin() const { return const_iterator(m_spans); }
00444         iterator       begin()       { return iterator(m_spans); }
00445 
00446     private:
00447         scanline32_u8(const self_type&);
00448         const self_type& operator = (const self_type&);
00449 
00450     private:
00451         int                   m_min_x;
00452         int                   m_last_x;
00453         int                   m_y;
00454         pod_array<cover_type> m_covers;
00455         span_array_type       m_spans;
00456     };
00457 
00458 
00459 
00460 
00461     //========================================================scanline32_u8_am
00462     // 
00463     // The scanline container with alpha-masking
00464     // 
00465     //------------------------------------------------------------------------
00466     template<class AlphaMask> 
00467     class scanline32_u8_am : public scanline32_u8
00468     {
00469     public:
00470         typedef scanline32_u8         base_type;
00471         typedef AlphaMask             alpha_mask_type;
00472         typedef base_type::cover_type cover_type;
00473         typedef base_type::coord_type coord_type;
00474 
00475 
00476         scanline32_u8_am() : base_type(), m_alpha_mask(0) {}
00477         scanline32_u8_am(const AlphaMask& am) : base_type(), m_alpha_mask(&am) {}
00478 
00479         //--------------------------------------------------------------------
00480         void finalize(int span_y)
00481         {
00482             base_type::finalize(span_y);
00483             if(m_alpha_mask)
00484             {
00485                 typename base_type::iterator span = base_type::begin();
00486                 unsigned count = base_type::num_spans();
00487                 do
00488                 {
00489                     m_alpha_mask->combine_hspan(span->x, 
00490                                                 base_type::y(), 
00491                                                 span->covers, 
00492                                                 span->len);
00493                     ++span;
00494                 }
00495                 while(--count);
00496             }
00497         }
00498 
00499     private:
00500         const AlphaMask* m_alpha_mask;
00501     };
00502 
00503 
00504 
00505 }
00506 
00507 #endif
00508 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines