1 //---------------------------------------------------------------------------- 2 // Anti-Grain Geometry - Version 2.2 3 // Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) 4 // 5 // Permission to copy, use, modify, sell and distribute this software 6 // is granted provided this copyright notice appears in all copies. 7 // This software is provided "as is" without express or implied 8 // warranty, and with no claim as to its suitability for any purpose. 9 // 10 //---------------------------------------------------------------------------- 11 // Contact: mcseem@antigrain.com 12 // mcseemagg@yahoo.com 13 // http://www.antigrain.com 14 //---------------------------------------------------------------------------- 15 16 #ifndef AGG_SCANLINE_U_INCLUDED 17 #define AGG_SCANLINE_U_INCLUDED 18 19 #include <string.h> 20 #include "agg_basics.h" 21 22 namespace agg 23 { 24 //==============================================================scanline_u 25 // 26 // Unpacked scanline container class 27 // 28 // This class is used to transfer data from a scanline rastyerizer 29 // to the rendering buffer. It's organized very simple. The class stores 30 // information of horizontal spans to render it into a pixel-map buffer. 31 // Each span has staring X, length, and an array of bytes that determine the 32 // cover-values for each pixel. 33 // Before using this class you should know the minimal and maximal pixel 34 // coordinates of your scanline. The protocol of using is: 35 // 1. reset(min_x, max_x) 36 // 2. add_cell() / add_span() - accumulate scanline. 37 // When forming one scanline the next X coordinate must be always greater 38 // than the last stored one, i.e. it works only with ordered coordinates. 39 // 3. Call finalize(y) and render the scanline. 40 // 3. Call reset_spans() to prepare for the new scanline. 41 // 42 // 4. Rendering: 43 // 44 // Scanline provides an iterator class that allows you to extract 45 // the spans and the cover values for each pixel. Be aware that clipping 46 // has not been done yet, so you should perform it yourself. 47 // Use scanline_u8::iterator to render spans: 48 //------------------------------------------------------------------------- 49 // 50 // int y = sl.y(); // Y-coordinate of the scanline 51 // 52 // ************************************ 53 // ...Perform vertical clipping here... 54 // ************************************ 55 // 56 // scanline_u8::const_iterator span = sl.begin(); 57 // 58 // unsigned char* row = m_rbuf->row(y); // The the address of the beginning 59 // // of the current row 60 // 61 // unsigned num_spans = sl.num_spans(); // Number of spans. It's guaranteed that 62 // // num_spans is always greater than 0. 63 // 64 // do 65 // { 66 // const scanline_u8::cover_type* covers = 67 // span->covers; // The array of the cover values 68 // 69 // int num_pix = span->len; // Number of pixels of the span. 70 // // Always greater than 0, still it's 71 // // better to use "int" instead of 72 // // "unsigned" because it's more 73 // // convenient for clipping 74 // int x = span->x; 75 // 76 // ************************************** 77 // ...Perform horizontal clipping here... 78 // ...you have x, covers, and pix_count.. 79 // ************************************** 80 // 81 // unsigned char* dst = row + x; // Calculate the start address of the row. 82 // // In this case we assume a simple 83 // // grayscale image 1-byte per pixel. 84 // do 85 // { 86 // *dst++ = *covers++; // Hypotetical rendering. 87 // } 88 // while(--num_pix); 89 // 90 // ++span; 91 // } 92 // while(--num_spans); // num_spans cannot be 0, so this loop is quite safe 93 //------------------------------------------------------------------------ 94 // 95 // The question is: why should we accumulate the whole scanline when we 96 // could render just separate spans when they're ready? 97 // That's because using the scaline is generally faster. When is consists 98 // of more than one span the conditions for the processor cash system 99 // are better, because switching between two different areas of memory 100 // (that can be very large) occures less frequently. 101 //------------------------------------------------------------------------ 102 template<class T> class scanline_u 103 { 104 public: 105 typedef T cover_type; 106 107 //-------------------------------------------------------------------- 108 struct span 109 { 110 int16 x; 111 int16 len; 112 cover_type* covers; 113 }; 114 115 typedef span* iterator; 116 typedef const span* const_iterator; 117 118 //-------------------------------------------------------------------- 119 ~scanline_u(); 120 scanline_u(); 121 122 void reset(int min_x, int max_x); 123 void add_cell(int x, unsigned cover); 124 void add_cells(int x, unsigned len, const T* covers); 125 void add_span(int x, unsigned len, unsigned cover); 126 void finalize(int y) { m_y = y; } 127 void reset_spans(); 128 129 int y() const { return m_y; } 130 unsigned num_spans() const { return unsigned(m_cur_span - m_spans); } 131 const_iterator begin() const { return m_spans + 1; } 132 iterator begin() { return m_spans + 1; } 133 134 private: 135 scanline_u<T>(const scanline_u<T>&); 136 const scanline_u<T>& operator = (const scanline_u<T>&); 137 138 private: 139 int m_min_x; 140 unsigned m_max_len; 141 int m_last_x; 142 int m_y; 143 cover_type* m_covers; 144 span* m_spans; 145 span* m_cur_span; 146 }; 147 148 149 150 //------------------------------------------------------------------------ 151 template<class T> scanline_u<T>::~scanline_u() 152 { 153 delete [] m_spans; 154 delete [] m_covers; 155 } 156 157 158 //------------------------------------------------------------------------ 159 template<class T> scanline_u<T>::scanline_u() : 160 m_min_x(0), 161 m_max_len(0), 162 m_last_x(0x7FFFFFF0), 163 m_covers(0), 164 m_spans(0), 165 m_cur_span(0) 166 { 167 } 168 169 170 //------------------------------------------------------------------------ 171 template<class T> void scanline_u<T>::reset(int min_x, int max_x) 172 { 173 unsigned max_len = max_x - min_x + 2; 174 if(max_len > m_max_len) 175 { 176 delete [] m_spans; 177 delete [] m_covers; 178 m_covers = new cover_type [max_len]; 179 m_spans = new span [max_len]; 180 m_max_len = max_len; 181 } 182 m_last_x = 0x7FFFFFF0; 183 m_min_x = min_x; 184 m_cur_span = m_spans; 185 } 186 187 188 //------------------------------------------------------------------------ 189 template<class T> inline void scanline_u<T>::reset_spans() 190 { 191 m_last_x = 0x7FFFFFF0; 192 m_cur_span = m_spans; 193 } 194 195 196 //------------------------------------------------------------------------ 197 template<class T> inline void scanline_u<T>::add_cell(int x, unsigned cover) 198 { 199 x -= m_min_x; 200 m_covers[x] = (unsigned char)cover; 201 if(x == m_last_x+1) 202 { 203 m_cur_span->len++; 204 } 205 else 206 { 207 m_cur_span++; 208 m_cur_span->x = (int16)(x + m_min_x); 209 m_cur_span->len = 1; 210 m_cur_span->covers = m_covers + x; 211 } 212 m_last_x = x; 213 } 214 215 216 //------------------------------------------------------------------------ 217 template<class T> void scanline_u<T>::add_cells(int x, unsigned len, const T* covers) 218 { 219 x -= m_min_x; 220 memcpy(m_covers + x, covers, len * sizeof(T)); 221 if(x == m_last_x+1) 222 { 223 m_cur_span->len += (int16)len; 224 } 225 else 226 { 227 m_cur_span++; 228 m_cur_span->x = (int16)(x + m_min_x); 229 m_cur_span->len = (int16)len; 230 m_cur_span->covers = m_covers + x; 231 } 232 m_last_x = x + len - 1; 233 } 234 235 236 //------------------------------------------------------------------------ 237 template<class T> void scanline_u<T>::add_span(int x, unsigned len, unsigned cover) 238 { 239 x -= m_min_x; 240 memset(m_covers + x, cover, len); 241 if(x == m_last_x+1) 242 { 243 m_cur_span->len += (int16)len; 244 } 245 else 246 { 247 m_cur_span++; 248 m_cur_span->x = (int16)(x + m_min_x); 249 m_cur_span->len = (int16)len; 250 m_cur_span->covers = m_covers + x; 251 } 252 m_last_x = x + len - 1; 253 } 254 255 256 //=============================================================scanline_u8 257 typedef scanline_u<int8u> scanline_u8; 258 259 //============================================================scanline_u16 260 typedef scanline_u<int16u> scanline_u16; 261 262 //============================================================scanline_u32 263 typedef scanline_u<int32u> scanline_u32; 264 265 266 //=============================================================scanline_am 267 // 268 // The scanline container with alpha-masking 269 // 270 //------------------------------------------------------------------------ 271 template<class AlphaMask, class CoverT> 272 class scanline_am : public scanline_u<CoverT> 273 { 274 public: 275 typedef AlphaMask alpha_mask_type; 276 typedef CoverT cover_type; 277 typedef scanline_u<CoverT> scanline_type; 278 279 scanline_am() : scanline_type(), m_alpha_mask(0) {} 280 scanline_am(const AlphaMask& am) : scanline_type(), m_alpha_mask(&am) {} 281 282 //-------------------------------------------------------------------- 283 void finalize(int span_y) 284 { 285 scanline_u<CoverT>::finalize(span_y); 286 if(m_alpha_mask) 287 { 288 typename scanline_type::iterator span = scanline_type::begin(); 289 unsigned count = scanline_type::num_spans(); 290 do 291 { 292 m_alpha_mask->combine_hspan(span->x, 293 scanline_type::y(), 294 span->covers, 295 span->len); 296 ++span; 297 } 298 while(--count); 299 } 300 } 301 302 private: 303 const AlphaMask* m_alpha_mask; 304 }; 305 306 307 //==========================================================scanline_u8_am 308 template<class AlphaMask> 309 class scanline_u8_am : public scanline_am<AlphaMask, int8u> 310 { 311 public: 312 typedef AlphaMask alpha_mask_type; 313 typedef int8u cover_type; 314 typedef scanline_am<alpha_mask_type, cover_type> self_type; 315 316 scanline_u8_am() : self_type() {} 317 scanline_u8_am(const AlphaMask& am) : self_type(am) {} 318 }; 319 320 } 321 322 #endif 323 324