Anti-Grain Geometry - AGG (libagg)
2.5
|
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