osgEarth 2.1.1
|
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