Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
  • 4 commits
  • 13 files changed
  • 0 comments
  • 1 contributor
12  Makefile
... ...
@@ -1,10 +1,12 @@
1 1
 MISPDIR=.
2 2
 include $(MISPDIR)/common.mak
3 3
 
4  
-OBJECTS=crt0.o isr.o luainit.o main.o
5  
-OURLIBS=m mm yaffs2 glue lua lfs freetype
  4
+OBJECTS=crt0.o isr.o luainit.o agg_test.o main.o
  5
+OURLIBS=m mm yaffs2 glue lua lfs agl
6 6
 
7  
-CFLAGS+=-I$(MISPDIR)/libm/include -I$(MISPDIR)/libmm/include -I$(MISPDIR)/libglue/include -I$(LUADIR)/src -I$(MISPDIR)/liblfs/include
  7
+INCFLAGS=-I$(MISPDIR)/libm/include -I$(MISPDIR)/libmm/include -I$(MISPDIR)/libglue/include -I$(LUADIR)/src -I$(MISPDIR)/liblfs/include -I$(MISPDIR)/libagl/include
  8
+CFLAGS+=$(INCFLAGS)
  9
+CXXFLAGS+=$(INCFLAGS)
8 10
 
9 11
 all: misp.bin
10 12
 
@@ -25,9 +27,13 @@ misp.elf: linker.ld $(OBJECTS) libs
25 27
 		--start-group -lbase -lcompiler-rt $(addprefix -l,$(OURLIBS)) --end-group
26 28
 	chmod -x $@
27 29
 
  30
+%.o: %.cpp
  31
+	$(compilexx-dep)
  32
+
28 33
 %.o: %.c
29 34
 	$(compile-dep)
30 35
 
  36
+
31 37
 libs:
32 38
 	set -e; \
33 39
 	for lib in $(OURLIBS); do \
141  agg_test.cpp
... ...
@@ -0,0 +1,141 @@
  1
+#include <stdlib.h>
  2
+#include <stdio.h>
  3
+#include <math.h>
  4
+#include <hw/csr.h>
  5
+#include "agg.h"
  6
+
  7
+enum
  8
+{
  9
+    width  = 640,
  10
+    height = 480
  11
+};
  12
+
  13
+
  14
+double random(double min, double max)
  15
+{
  16
+    int r = (rand() << 15) | rand();
  17
+    return ((r & 0xFFFFFFF) / double(0xFFFFFFF + 1)) * (max - min) + min;
  18
+}
  19
+
  20
+
  21
+void draw_ellipse(agg::rasterizer& ras,
  22
+                  double x,  double y,
  23
+                  double rx, double ry)
  24
+{
  25
+    int i;
  26
+    ras.move_to_d(x + rx, y);
  27
+
  28
+    // Here we have a fixed number of approximation steps, namely 360
  29
+    // while in reality it's supposed to be smarter.
  30
+    for(i = 1; i < 360; i++)
  31
+    {
  32
+        double a = double(i) * 3.1415926 / 180.0;
  33
+        ras.line_to_d(x + cos(a) * rx, y + sin(a) * ry);
  34
+    }
  35
+}
  36
+
  37
+
  38
+void draw_line(agg::rasterizer& ras,
  39
+               double x1, double y1, 
  40
+               double x2, double y2,
  41
+               double width)
  42
+{
  43
+
  44
+    double dx = x2 - x1;
  45
+    double dy = y2 - y1;
  46
+    double d = sqrt(dx*dx + dy*dy);
  47
+    
  48
+    dx = width * (y2 - y1) / d;
  49
+    dy = width * (x2 - x1) / d;
  50
+
  51
+    ras.move_to_d(x1 - dx,  y1 + dy);
  52
+    ras.line_to_d(x2 - dx,  y2 + dy);
  53
+    ras.line_to_d(x2 + dx,  y2 - dy);
  54
+    ras.line_to_d(x1 + dx,  y1 - dy);
  55
+}
  56
+
  57
+static void start_fb(unsigned char *addr)
  58
+{
  59
+    fb_base_write((unsigned int)addr);
  60
+    fb_enable_write(1);
  61
+}
  62
+
  63
+extern "C" void agg_test(void);
  64
+void agg_test(void)
  65
+{
  66
+    // Allocate the framebuffer
  67
+    unsigned char* buf = new unsigned char[width * height * 4];
  68
+
  69
+    start_fb(buf);
  70
+
  71
+    // Create the rendering buffer 
  72
+    agg::rendering_buffer rbuf(buf, width, height, width * 4);
  73
+
  74
+    // Create the renderer and the rasterizer
  75
+    agg::renderer<agg::span_rgba32> ren(rbuf);
  76
+    agg::rasterizer ras;
  77
+
  78
+    // Setup the rasterizer
  79
+    ras.gamma(1.3);
  80
+    ras.filling_rule(agg::fill_even_odd);
  81
+
  82
+    ren.clear(agg::rgba8(255, 255, 255));
  83
+
  84
+    int i;
  85
+
  86
+    // Draw random polygons
  87
+    for(i = 0; i < 10; i++)
  88
+    {
  89
+        int n = rand() % 6 + 3;
  90
+
  91
+        // Make the polygon. One can call move_to() more than once. 
  92
+        // In this case the rasterizer behaves like Win32 API PolyPolygon().
  93
+        ras.move_to_d(random(-30, rbuf.width() + 30), 
  94
+                      random(-30, rbuf.height() + 30));
  95
+
  96
+        int j;
  97
+        for(j = 1; j < n; j++)
  98
+        {
  99
+            ras.line_to_d(random(-30, rbuf.width() + 30), 
  100
+                          random(-30, rbuf.height() + 30));
  101
+        }
  102
+
  103
+        // Render
  104
+        ras.render(ren, agg::rgba8(rand() & 0xFF, 
  105
+                                   rand() & 0xFF, 
  106
+                                   rand() & 0xFF, 
  107
+                                   rand() & 0xFF));
  108
+    }
  109
+
  110
+    // Draw random ellipses
  111
+    for(i = 0; i < 50; i++)
  112
+    {
  113
+        draw_ellipse(ras, 
  114
+                     random(-30, rbuf.width()  + 30), 
  115
+                     random(-30, rbuf.height() + 30),
  116
+                     random(3, 50), 
  117
+                     random(3, 50));
  118
+        ras.render(ren, agg::rgba8(rand() & 0x7F, 
  119
+                                   rand() & 0x7F, 
  120
+                                   rand() & 0x7F,
  121
+                                  (rand() & 0x7F) + 100));
  122
+    }
  123
+
  124
+    // Draw random straight lines
  125
+    for(i = 0; i < 20; i++)
  126
+    {
  127
+        draw_line(ras, 
  128
+                  random(-30, rbuf.width()  + 30), 
  129
+                  random(-30, rbuf.height() + 30),
  130
+                  random(-30, rbuf.width()  + 30), 
  131
+                  random(-30, rbuf.height() + 30),
  132
+                  random(0.1, 10));
  133
+
  134
+        ras.render(ren, agg::rgba8(rand() & 0x7F, 
  135
+                                   rand() & 0x7F, 
  136
+                                   rand() & 0x7F));
  137
+    }
  138
+
  139
+    delete [] buf;
  140
+}
  141
+
3  isr.c
... ...
@@ -1,5 +1,4 @@
1  
-#include <hw/uart.h>
2  
-#include <interrupt.h>
  1
+#include <hw/csr.h>
3 2
 #include <irq.h>
4 3
 #include <uart.h>
5 4
 
22  libagl/Makefile
... ...
@@ -0,0 +1,22 @@
  1
+MISPDIR=..
  2
+include $(MISPDIR)/common.mak
  3
+
  4
+CXXFLAGS+=-I$(MISPDIR)/libagl/include -I$(MISPDIR)/libm/include
  5
+OBJECTS=agg.o
  6
+
  7
+all: libagl.a
  8
+
  9
+# pull in dependency info for *existing* .o files
  10
+-include $(OBJECTS:.o=.d)
  11
+
  12
+libagl.a: $(OBJECTS)
  13
+	$(AR) clr libagl.a $(OBJECTS)
  14
+	$(RANLIB) libagl.a
  15
+
  16
+%.o: %.cpp
  17
+	$(compilexx-dep)
  18
+
  19
+.PHONY: clean
  20
+
  21
+clean:
  22
+	rm -f $(OBJECTS) $(OBJECTS:.o=.d) libagl.a .*~ *~
892  libagl/agg.cpp
... ...
@@ -0,0 +1,892 @@
  1
+//----------------------------------------------------------------------------
  2
+// Anti-Grain Geometry - Version 2.1 Lite 
  3
+// Copyright (C) 2002-2003 Maxim Shemanarev (McSeem)
  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
+// The author gratefully acknowleges the support of David Turner, 
  11
+// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType 
  12
+// libray - in producing this work. See http://www.freetype.org for details.
  13
+//
  14
+//----------------------------------------------------------------------------
  15
+// Contact: mcseem@antigrain.com
  16
+//          mcseemagg@yahoo.com
  17
+//          http://www.antigrain.com
  18
+//----------------------------------------------------------------------------
  19
+//
  20
+// Class outline - implementation.
  21
+//
  22
+// Initially the rendering algorithm was designed by David Turner and the 
  23
+// other authors of the FreeType library - see the above notice. I nearly 
  24
+// created a similar renderer, but still I was far from David's work. 
  25
+// I completely redesigned the original code and adapted it for Anti-Grain 
  26
+// ideas. Two functions - render_line and render_scanline are the core of 
  27
+// the algorithm - they calculate the exact coverage of each pixel cell
  28
+// of the polygon. I left these functions almost as is, because there's 
  29
+// no way to improve the perfection - hats off to David and his group!
  30
+//
  31
+// All other code is very different from the original. 
  32
+// 
  33
+//----------------------------------------------------------------------------
  34
+
  35
+
  36
+#include <math.h>
  37
+#include "agg.h"
  38
+
  39
+
  40
+namespace agg
  41
+{
  42
+
  43
+
  44
+    //========================================================================
  45
+
  46
+    //------------------------------------------------------------------------
  47
+    rendering_buffer::~rendering_buffer()
  48
+    {
  49
+        delete [] m_rows;
  50
+    }
  51
+
  52
+
  53
+    //------------------------------------------------------------------------
  54
+    rendering_buffer::rendering_buffer(unsigned char* buf,
  55
+                                       unsigned width, 
  56
+                                       unsigned height,
  57
+                                       int      stride) :
  58
+        m_buf(0),
  59
+        m_rows(0),
  60
+        m_width(0),
  61
+        m_height(0),
  62
+        m_stride(0),
  63
+        m_max_height(0)
  64
+    {
  65
+        attach(buf, width, height, stride);
  66
+    }
  67
+
  68
+
  69
+    //------------------------------------------------------------------------
  70
+    void rendering_buffer::attach(unsigned char* buf,
  71
+                                  unsigned width, 
  72
+                                  unsigned height,
  73
+                                  int      stride)
  74
+    {
  75
+        m_buf = buf;
  76
+        m_width = width;
  77
+        m_height = height;
  78
+        m_stride = stride;
  79
+        if(height > m_max_height)
  80
+        {
  81
+            delete [] m_rows;
  82
+            m_rows = new unsigned char* [m_max_height = height];
  83
+        }
  84
+
  85
+        unsigned char* row_ptr = m_buf;
  86
+
  87
+        if(stride < 0)
  88
+        {
  89
+            row_ptr = m_buf - int(height - 1) * stride;
  90
+        }
  91
+
  92
+        unsigned char** rows = m_rows;
  93
+
  94
+        while(height--)
  95
+        {
  96
+            *rows++ = row_ptr;
  97
+            row_ptr += stride;
  98
+        }
  99
+    }
  100
+
  101
+
  102
+    //========================================================================
  103
+
  104
+    //------------------------------------------------------------------------
  105
+    scanline::~scanline()
  106
+    {
  107
+        delete [] m_counts;
  108
+        delete [] m_start_ptrs;
  109
+        delete [] m_covers;
  110
+    }
  111
+
  112
+
  113
+    //------------------------------------------------------------------------
  114
+    scanline::scanline()
  115
+        : m_min_x(0),
  116
+          m_max_len(0),
  117
+          m_dx(0),
  118
+          m_dy(0),
  119
+          m_last_x(0x7FFF),
  120
+          m_last_y(0x7FFF),
  121
+          m_covers(0),
  122
+          m_start_ptrs(0),
  123
+          m_counts(0),
  124
+          m_num_spans(0),
  125
+          m_cur_start_ptr(0),
  126
+          m_cur_count(0)
  127
+    {
  128
+    }
  129
+
  130
+
  131
+    //------------------------------------------------------------------------
  132
+    void scanline::reset(int min_x, int max_x, int dx, int dy)
  133
+    {
  134
+        unsigned max_len = max_x - min_x + 2;
  135
+        if(max_len > m_max_len)
  136
+        {
  137
+            delete [] m_counts;
  138
+            delete [] m_start_ptrs;
  139
+            delete [] m_covers;
  140
+            m_covers     = new unsigned char  [max_len];
  141
+            m_start_ptrs = new unsigned char* [max_len];
  142
+            m_counts     = new int16u[max_len];
  143
+            m_max_len    = max_len;
  144
+        }
  145
+        m_dx            = dx;
  146
+        m_dy            = dy;
  147
+        m_last_x        = 0x7FFF;
  148
+        m_last_y        = 0x7FFF;
  149
+        m_min_x         = min_x;
  150
+        m_cur_count     = m_counts;
  151
+        m_cur_start_ptr = m_start_ptrs;
  152
+        m_num_spans     = 0;
  153
+    }
  154
+
  155
+
  156
+    //------------------------------------------------------------------------
  157
+    void scanline::add_span(int x, int y, unsigned num, unsigned cover)
  158
+    {
  159
+        x -= m_min_x;
  160
+
  161
+        memset(m_covers + x, cover, num);
  162
+        if(x == m_last_x+1)
  163
+        {
  164
+            (*m_cur_count) += (int16u)num;
  165
+        }
  166
+        else
  167
+        {
  168
+            *++m_cur_count = (int16u)num;
  169
+            *++m_cur_start_ptr = m_covers + x;
  170
+            m_num_spans++;
  171
+        }
  172
+        m_last_x = x + num - 1;
  173
+        m_last_y = y;
  174
+    }
  175
+
  176
+
  177
+
  178
+    //========================================================================
  179
+
  180
+    //------------------------------------------------------------------------
  181
+    const int8u rasterizer::s_default_gamma[] = 
  182
+    {
  183
+          0,  0,  1,  1,  2,  2,  3,  4,  4,  5,  5,  6,  7,  7,  8,  8,
  184
+          9, 10, 10, 11, 11, 12, 13, 13, 14, 14, 15, 16, 16, 17, 18, 18,
  185
+         19, 19, 20, 21, 21, 22, 22, 23, 24, 24, 25, 25, 26, 27, 27, 28,
  186
+         29, 29, 30, 30, 31, 32, 32, 33, 34, 34, 35, 36, 36, 37, 37, 38,
  187
+         39, 39, 40, 41, 41, 42, 43, 43, 44, 45, 45, 46, 47, 47, 48, 49,
  188
+         49, 50, 51, 51, 52, 53, 53, 54, 55, 55, 56, 57, 57, 58, 59, 60,
  189
+         60, 61, 62, 62, 63, 64, 65, 65, 66, 67, 68, 68, 69, 70, 71, 71,
  190
+         72, 73, 74, 74, 75, 76, 77, 78, 78, 79, 80, 81, 82, 83, 83, 84,
  191
+         85, 86, 87, 88, 89, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
  192
+        100,101,101,102,103,104,105,106,107,108,109,110,111,112,114,115,
  193
+        116,117,118,119,120,121,122,123,124,126,127,128,129,130,131,132,
  194
+        134,135,136,137,139,140,141,142,144,145,146,147,149,150,151,153,
  195
+        154,155,157,158,159,161,162,164,165,166,168,169,171,172,174,175,
  196
+        177,178,180,181,183,184,186,188,189,191,192,194,195,197,199,200,
  197
+        202,204,205,207,209,210,212,214,215,217,219,220,222,224,225,227,
  198
+        229,230,232,234,236,237,239,241,242,244,246,248,249,251,253,255
  199
+    };
  200
+
  201
+
  202
+
  203
+
  204
+
  205
+    //========================================================================
  206
+    enum
  207
+    {
  208
+        not_closed    = 1,
  209
+        sort_required = 2
  210
+    };
  211
+
  212
+    //------------------------------------------------------------------------
  213
+    inline void cell::set_cover(int c, int a)
  214
+    {
  215
+        cover = c;
  216
+        area = a;
  217
+    }
  218
+
  219
+    //------------------------------------------------------------------------
  220
+    inline void cell::add_cover(int c, int a)
  221
+    {
  222
+        cover += c;
  223
+        area += a;
  224
+    }
  225
+
  226
+    //------------------------------------------------------------------------
  227
+    inline void cell::set_coord(int cx, int cy)
  228
+    {
  229
+        x = int16(cx);
  230
+        y = int16(cy);
  231
+        packed_coord = (cy << 16) + cx;
  232
+    }
  233
+
  234
+    //------------------------------------------------------------------------
  235
+    inline void cell::set(int cx, int cy, int c, int a)
  236
+    {
  237
+        x = int16(cx);
  238
+        y = int16(cy);
  239
+        packed_coord = (cy << 16) + cx;
  240
+        cover = c;
  241
+        area = a;
  242
+    }
  243
+
  244
+    //------------------------------------------------------------------------
  245
+    outline::~outline()
  246
+    {
  247
+        delete [] m_sorted_cells;
  248
+        if(m_num_blocks)
  249
+        {
  250
+            cell** ptr = m_cells + m_num_blocks - 1;
  251
+            while(m_num_blocks--)
  252
+            {
  253
+                delete [] *ptr;
  254
+                ptr--;
  255
+            }
  256
+            delete [] m_cells;
  257
+        }
  258
+    }
  259
+
  260
+
  261
+    //------------------------------------------------------------------------
  262
+    outline::outline() :
  263
+        m_num_blocks(0),
  264
+        m_max_blocks(0),
  265
+        m_cur_block(0),
  266
+        m_num_cells(0),
  267
+        m_cells(0),
  268
+        m_cur_cell_ptr(0),
  269
+        m_sorted_cells(0),
  270
+        m_sorted_size(0),
  271
+        m_cur_x(0),
  272
+        m_cur_y(0),
  273
+        m_close_x(0),
  274
+        m_close_y(0),
  275
+        m_min_x(0x7FFFFFFF),
  276
+        m_min_y(0x7FFFFFFF),
  277
+        m_max_x(-0x7FFFFFFF),
  278
+        m_max_y(-0x7FFFFFFF),
  279
+        m_flags(sort_required)
  280
+    {
  281
+        m_cur_cell.set(0x7FFF, 0x7FFF, 0, 0);
  282
+    }
  283
+
  284
+
  285
+    //------------------------------------------------------------------------
  286
+    void outline::reset()
  287
+    { 
  288
+        m_num_cells = 0; 
  289
+        m_cur_block = 0;
  290
+        m_cur_cell.set(0x7FFF, 0x7FFF, 0, 0);
  291
+        m_flags |= sort_required;
  292
+        m_flags &= ~not_closed;
  293
+        m_min_x =  0x7FFFFFFF;
  294
+        m_min_y =  0x7FFFFFFF;
  295
+        m_max_x = -0x7FFFFFFF;
  296
+        m_max_y = -0x7FFFFFFF;
  297
+    }
  298
+
  299
+
  300
+
  301
+    //------------------------------------------------------------------------
  302
+    void outline::allocate_block()
  303
+    {
  304
+        if(m_cur_block >= m_num_blocks)
  305
+        {
  306
+            if(m_num_blocks >= m_max_blocks)
  307
+            {
  308
+                cell** new_cells = new cell* [m_max_blocks + cell_block_pool];
  309
+                if(m_cells)
  310
+                {
  311
+                    memcpy(new_cells, m_cells, m_max_blocks * sizeof(cell*));
  312
+                    delete [] m_cells;
  313
+                }
  314
+                m_cells = new_cells;
  315
+                m_max_blocks += cell_block_pool;
  316
+            }
  317
+            m_cells[m_num_blocks++] = new cell [unsigned(cell_block_size)];
  318
+        }
  319
+        m_cur_cell_ptr = m_cells[m_cur_block++];
  320
+    }
  321
+
  322
+
  323
+    //------------------------------------------------------------------------
  324
+    inline void outline::add_cur_cell()
  325
+    {
  326
+        if(m_cur_cell.area | m_cur_cell.cover)
  327
+        {
  328
+            if((m_num_cells & cell_block_mask) == 0)
  329
+            {
  330
+                if(m_num_blocks >= cell_block_limit) return;
  331
+                allocate_block();
  332
+            }
  333
+            *m_cur_cell_ptr++ = m_cur_cell;
  334
+            m_num_cells++;
  335
+        }
  336
+    }
  337
+
  338
+
  339
+
  340
+    //------------------------------------------------------------------------
  341
+    inline void outline::set_cur_cell(int x, int y)
  342
+    {
  343
+        if(m_cur_cell.packed_coord != (y << 16) + x)
  344
+        {
  345
+            add_cur_cell();
  346
+            m_cur_cell.set(x, y, 0, 0);
  347
+        }
  348
+    }
  349
+
  350
+
  351
+
  352
+    //------------------------------------------------------------------------
  353
+    inline void outline::render_scanline(int ey, int x1, int y1, int x2, int y2)
  354
+    {
  355
+        int ex1 = x1 >> poly_base_shift;
  356
+        int ex2 = x2 >> poly_base_shift;
  357
+        int fx1 = x1 & poly_base_mask;
  358
+        int fx2 = x2 & poly_base_mask;
  359
+
  360
+        int delta, p, first, dx;
  361
+        int incr, lift, mod, rem;
  362
+
  363
+        //trivial case. Happens often
  364
+        if(y1 == y2)
  365
+        {
  366
+            set_cur_cell(ex2, ey);
  367
+            return;
  368
+        }
  369
+
  370
+        //everything is located in a single cell.  That is easy!
  371
+        if(ex1 == ex2)
  372
+        {
  373
+            delta = y2 - y1;
  374
+            m_cur_cell.add_cover(delta, (fx1 + fx2) * delta);
  375
+            return;
  376
+        }
  377
+
  378
+        //ok, we'll have to render a run of adjacent cells on the same
  379
+        //scanline...
  380
+        p     = (poly_base_size - fx1) * (y2 - y1);
  381
+        first = poly_base_size;
  382
+        incr  = 1;
  383
+
  384
+        dx = x2 - x1;
  385
+
  386
+        if(dx < 0)
  387
+        {
  388
+            p     = fx1 * (y2 - y1);
  389
+            first = 0;
  390
+            incr  = -1;
  391
+            dx    = -dx;
  392
+        }
  393
+
  394
+        delta = p / dx;
  395
+        mod   = p % dx;
  396
+
  397
+        if(mod < 0)
  398
+        {
  399
+            delta--;
  400
+            mod += dx;
  401
+        }
  402
+
  403
+        m_cur_cell.add_cover(delta, (fx1 + first) * delta);
  404
+
  405
+        ex1 += incr;
  406
+        set_cur_cell(ex1, ey);
  407
+        y1  += delta;
  408
+
  409
+        if(ex1 != ex2)
  410
+        {
  411
+            p     = poly_base_size * (y2 - y1 + delta);
  412
+            lift  = p / dx;
  413
+            rem   = p % dx;
  414
+
  415
+            if (rem < 0)
  416
+            {
  417
+                lift--;
  418
+                rem += dx;
  419
+            }
  420
+
  421
+            mod -= dx;
  422
+
  423
+            while (ex1 != ex2)
  424
+            {
  425
+                delta = lift;
  426
+                mod  += rem;
  427
+                if(mod >= 0)
  428
+                {
  429
+                    mod -= dx;
  430
+                    delta++;
  431
+                }
  432
+
  433
+                m_cur_cell.add_cover(delta, (poly_base_size) * delta);
  434
+                y1  += delta;
  435
+                ex1 += incr;
  436
+                set_cur_cell(ex1, ey);
  437
+            }
  438
+        }
  439
+        delta = y2 - y1;
  440
+        m_cur_cell.add_cover(delta, (fx2 + poly_base_size - first) * delta);
  441
+    }
  442
+
  443
+
  444
+
  445
+
  446
+
  447
+
  448
+    //------------------------------------------------------------------------
  449
+    void outline::render_line(int x1, int y1, int x2, int y2)
  450
+    {
  451
+        int ey1 = y1 >> poly_base_shift;
  452
+        int ey2 = y2 >> poly_base_shift;
  453
+        int fy1 = y1 & poly_base_mask;
  454
+        int fy2 = y2 & poly_base_mask;
  455
+
  456
+        int dx, dy, x_from, x_to;
  457
+        int p, rem, mod, lift, delta, first, incr;
  458
+
  459
+        if(ey1   < m_min_y) m_min_y = ey1;
  460
+        if(ey1+1 > m_max_y) m_max_y = ey1+1;
  461
+        if(ey2   < m_min_y) m_min_y = ey2;
  462
+        if(ey2+1 > m_max_y) m_max_y = ey2+1;
  463
+
  464
+        dx = x2 - x1;
  465
+        dy = y2 - y1;
  466
+
  467
+        //everything is on a single scanline
  468
+        if(ey1 == ey2)
  469
+        {
  470
+            render_scanline(ey1, x1, fy1, x2, fy2);
  471
+            return;
  472
+        }
  473
+
  474
+        //Vertical line - we have to calculate start and end cells,
  475
+        //and then - the common values of the area and coverage for
  476
+        //all cells of the line. We know exactly there's only one 
  477
+        //cell, so, we don't have to call render_scanline().
  478
+        incr  = 1;
  479
+        if(dx == 0)
  480
+        {
  481
+            int ex = x1 >> poly_base_shift;
  482
+            int two_fx = (x1 - (ex << poly_base_shift)) << 1;
  483
+            int area;
  484
+
  485
+            first = poly_base_size;
  486
+            if(dy < 0)
  487
+            {
  488
+                first = 0;
  489
+                incr  = -1;
  490
+            }
  491
+
  492
+            x_from = x1;
  493
+
  494
+            //render_scanline(ey1, x_from, fy1, x_from, first);
  495
+            delta = first - fy1;
  496
+            m_cur_cell.add_cover(delta, two_fx * delta);
  497
+
  498
+            ey1 += incr;
  499
+            set_cur_cell(ex, ey1);
  500
+
  501
+            delta = first + first - poly_base_size;
  502
+            area = two_fx * delta;
  503
+            while(ey1 != ey2)
  504
+            {
  505
+                //render_scanline(ey1, x_from, poly_base_size - first, x_from, first);
  506
+                m_cur_cell.set_cover(delta, area);
  507
+                ey1 += incr;
  508
+                set_cur_cell(ex, ey1);
  509
+            }
  510
+            //render_scanline(ey1, x_from, poly_base_size - first, x_from, fy2);
  511
+            delta = fy2 - poly_base_size + first;
  512
+            m_cur_cell.add_cover(delta, two_fx * delta);
  513
+            return;
  514
+        }
  515
+
  516
+        //ok, we have to render several scanlines
  517
+        p     = (poly_base_size - fy1) * dx;
  518
+        first = poly_base_size;
  519
+
  520
+        if(dy < 0)
  521
+        {
  522
+            p     = fy1 * dx;
  523
+            first = 0;
  524
+            incr  = -1;
  525
+            dy    = -dy;
  526
+        }
  527
+
  528
+        delta = p / dy;
  529
+        mod   = p % dy;
  530
+
  531
+        if(mod < 0)
  532
+        {
  533
+            delta--;
  534
+            mod += dy;
  535
+        }
  536
+
  537
+        x_from = x1 + delta;
  538
+        render_scanline(ey1, x1, fy1, x_from, first);
  539
+
  540
+        ey1 += incr;
  541
+        set_cur_cell(x_from >> poly_base_shift, ey1);
  542
+
  543
+        if(ey1 != ey2)
  544
+        {
  545
+            p     = poly_base_size * dx;
  546
+            lift  = p / dy;
  547
+            rem   = p % dy;
  548
+
  549
+            if(rem < 0)
  550
+            {
  551
+                lift--;
  552
+                rem += dy;
  553
+            }
  554
+            mod -= dy;
  555
+
  556
+            while(ey1 != ey2)
  557
+            {
  558
+                delta = lift;
  559
+                mod  += rem;
  560
+                if (mod >= 0)
  561
+                {
  562
+                    mod -= dy;
  563
+                    delta++;
  564
+                }
  565
+
  566
+                x_to = x_from + delta;
  567
+                render_scanline(ey1, x_from, poly_base_size - first, x_to, first);
  568
+                x_from = x_to;
  569
+
  570
+                ey1 += incr;
  571
+                set_cur_cell(x_from >> poly_base_shift, ey1);
  572
+            }
  573
+        }
  574
+        render_scanline(ey1, x_from, poly_base_size - first, x2, fy2);
  575
+    }
  576
+
  577
+
  578
+    //------------------------------------------------------------------------
  579
+    void outline::move_to(int x, int y)
  580
+    {
  581
+        if((m_flags & sort_required) == 0) reset();
  582
+        if(m_flags & not_closed) line_to(m_close_x, m_close_y);
  583
+        set_cur_cell(x >> poly_base_shift, y >> poly_base_shift);
  584
+        m_close_x = m_cur_x = x;
  585
+        m_close_y = m_cur_y = y;
  586
+    }
  587
+
  588
+
  589
+
  590
+    //------------------------------------------------------------------------
  591
+    void outline::line_to(int x, int y)
  592
+    {
  593
+        if((m_flags & sort_required) && ((m_cur_x ^ x) | (m_cur_y ^ y)))
  594
+        {
  595
+            int c;
  596
+
  597
+            c = m_cur_x >> poly_base_shift;
  598
+            if(c < m_min_x) m_min_x = c;
  599
+            ++c;
  600
+            if(c > m_max_x) m_max_x = c;
  601
+
  602
+            c = x >> poly_base_shift;
  603
+            if(c < m_min_x) m_min_x = c;
  604
+            ++c;
  605
+            if(c > m_max_x) m_max_x = c;
  606
+
  607
+            render_line(m_cur_x, m_cur_y, x, y);
  608
+            m_cur_x = x;
  609
+            m_cur_y = y;
  610
+            m_flags |= not_closed;
  611
+        }
  612
+    }
  613
+
  614
+
  615
+    enum
  616
+    {
  617
+        qsort_threshold = 9
  618
+    };
  619
+
  620
+
  621
+    //------------------------------------------------------------------------
  622
+    template <class T> static inline void swap_cells(T* a, T* b)
  623
+    {
  624
+        T temp = *a;
  625
+        *a = *b;
  626
+        *b = temp;
  627
+    }
  628
+
  629
+    //------------------------------------------------------------------------
  630
+    template <class T> static inline bool less_than(T* a, T* b)
  631
+    {
  632
+        return (*a)->packed_coord < (*b)->packed_coord;
  633
+    }
  634
+
  635
+
  636
+
  637
+    //------------------------------------------------------------------------
  638
+    void outline::qsort_cells(cell** start, unsigned num)
  639
+    {
  640
+        cell**  stack[80];
  641
+        cell*** top; 
  642
+        cell**  limit;
  643
+        cell**  base;
  644
+
  645
+        limit = start + num;
  646
+        base  = start;
  647
+        top   = stack;
  648
+
  649
+        for (;;)
  650
+        {
  651
+            int len = int(limit - base);
  652
+
  653
+            cell** i;
  654
+            cell** j;
  655
+            cell** pivot;
  656
+
  657
+            if(len > qsort_threshold)
  658
+            {
  659
+                // we use base + len/2 as the pivot
  660
+                pivot = base + len / 2;
  661
+                swap_cells(base, pivot);
  662
+
  663
+                i = base + 1;
  664
+                j = limit - 1;
  665
+
  666
+                // now ensure that *i <= *base <= *j 
  667
+                if(less_than(j, i))
  668
+                {
  669
+                    swap_cells(i, j);
  670
+                }
  671
+
  672
+                if(less_than(base, i))
  673
+                {
  674
+                    swap_cells(base, i);
  675
+                }
  676
+
  677
+                if(less_than(j, base))
  678
+                {
  679
+                    swap_cells(base, j);
  680
+                }
  681
+
  682
+                for(;;)
  683
+                {
  684
+                    do i++; while( less_than(i, base) );
  685
+                    do j--; while( less_than(base, j) );
  686
+
  687
+                    if ( i > j )
  688
+                    {
  689
+                        break;
  690
+                    }
  691
+
  692
+                    swap_cells(i, j);
  693
+                }
  694
+
  695
+                swap_cells(base, j);
  696
+
  697
+                // now, push the largest sub-array
  698
+                if(j - base > limit - i)
  699
+                {
  700
+                    top[0] = base;
  701
+                    top[1] = j;
  702
+                    base   = i;
  703
+                }
  704
+                else
  705
+                {
  706
+                    top[0] = i;
  707
+                    top[1] = limit;
  708
+                    limit  = j;
  709
+                }
  710
+                top += 2;
  711
+            }
  712
+            else
  713
+            {
  714
+                // the sub-array is small, perform insertion sort
  715
+                j = base;
  716
+                i = j + 1;
  717
+
  718
+                for(; i < limit; j = i, i++)
  719
+                {
  720
+                    for(; less_than(j + 1, j); j--)
  721
+                    {
  722
+                        swap_cells(j + 1, j);
  723
+                        if (j == base)
  724
+                        {
  725
+                            break;
  726
+                        }
  727
+                    }
  728
+                }
  729
+                if(top > stack)
  730
+                {
  731
+                    top  -= 2;
  732
+                    base  = top[0];
  733
+                    limit = top[1];
  734
+                }
  735
+                else
  736
+                {
  737
+                    break;
  738
+                }
  739
+            }
  740
+        }
  741
+    }
  742
+
  743
+
  744
+
  745
+
  746
+
  747
+    //------------------------------------------------------------------------
  748
+    void outline::sort_cells()
  749
+    {
  750
+        if(m_num_cells == 0) return;
  751
+        if(m_num_cells > m_sorted_size)
  752
+        {
  753
+            delete [] m_sorted_cells;
  754
+            m_sorted_size = m_num_cells;
  755
+            m_sorted_cells = new cell* [m_num_cells + 1];
  756
+        }
  757
+
  758
+        cell** sorted_ptr = m_sorted_cells;
  759
+        cell** block_ptr = m_cells;
  760
+        cell*  cell_ptr;
  761
+
  762
+        unsigned nb = m_num_cells >> cell_block_shift;
  763
+        unsigned i;
  764
+
  765
+        while(nb--)
  766
+        {
  767
+            cell_ptr = *block_ptr++;
  768
+            i = cell_block_size;
  769
+            while(i--) 
  770
+            {
  771
+                *sorted_ptr++ = cell_ptr++;
  772
+            }
  773
+        }
  774
+
  775
+        cell_ptr = *block_ptr++;
  776
+        i = m_num_cells & cell_block_mask;
  777
+        while(i--) 
  778
+        {
  779
+            *sorted_ptr++ = cell_ptr++;
  780
+        }
  781
+        m_sorted_cells[m_num_cells] = 0;
  782
+        qsort_cells(m_sorted_cells, m_num_cells);
  783
+    }
  784
+
  785
+
  786
+
  787
+
  788
+    //------------------------------------------------------------------------
  789
+    const cell* const* outline::cells()
  790
+    {
  791
+        if(m_flags & not_closed)
  792
+        {
  793
+            line_to(m_close_x, m_close_y);
  794
+            m_flags &= ~not_closed;
  795
+        }
  796
+
  797
+        //Perform sort only the first time.
  798
+        if(m_flags & sort_required)
  799
+        {
  800
+            add_cur_cell();
  801
+            if(m_num_cells == 0) return 0;
  802
+            sort_cells();
  803
+            m_flags &= ~sort_required;
  804
+        }
  805
+        return m_sorted_cells;
  806
+    }
  807
+
  808
+
  809
+
  810
+    //------------------------------------------------------------------------
  811
+    void rasterizer::gamma(double g)
  812
+    {
  813
+        unsigned i;
  814
+        for(i = 0; i < 256; i++)
  815
+        {
  816
+            m_gamma[i] = (unsigned char)(pow(double(i) / 255.0, g) * 255.0);
  817
+        }
  818
+    }
  819
+
  820
+
  821
+    //------------------------------------------------------------------------
  822
+    void rasterizer::gamma(const int8u* g)
  823
+    {
  824
+        memcpy(m_gamma, g, sizeof(m_gamma));
  825
+    }
  826
+
  827
+
  828
+    //------------------------------------------------------------------------
  829
+    bool rasterizer::hit_test(int tx, int ty)
  830
+    {
  831
+        const cell* const* cells = m_outline.cells();
  832
+        if(m_outline.num_cells() == 0) return false;
  833
+
  834
+        int x, y;
  835
+        int cover;
  836
+        int alpha;
  837
+        int area;
  838
+
  839
+        cover = 0;
  840
+        const cell* cur_cell = *cells++;
  841
+        for(;;)
  842
+        {
  843
+            const cell* start_cell = cur_cell;
  844
+
  845
+            int coord  = cur_cell->packed_coord;
  846
+            x = cur_cell->x;
  847
+            y = cur_cell->y;
  848
+
  849
+            if(y > ty) return false;
  850
+
  851
+            area   = start_cell->area;
  852
+            cover += start_cell->cover;
  853
+
  854
+            while((cur_cell = *cells++) != 0)
  855
+            {
  856
+                if(cur_cell->packed_coord != coord) break;
  857
+                area  += cur_cell->area;
  858
+                cover += cur_cell->cover;
  859
+            }
  860
+
  861
+            if(area)
  862
+            {
  863
+                alpha = calculate_alpha((cover << (poly_base_shift + 1)) - area);
  864
+                if(alpha)
  865
+                {
  866
+                    if(tx == x && ty == y) return true;
  867
+                }
  868
+                x++;
  869
+            }
  870
+
  871
+            if(!cur_cell) break;
  872
+
  873
+            if(cur_cell->x > x)
  874
+            {
  875
+                alpha = calculate_alpha(cover << (poly_base_shift + 1));
  876
+                if(alpha)
  877
+                {
  878
+                    if(ty == y && tx >= x && tx <= cur_cell->x) return true;
  879
+                }
  880
+            }
  881
+        }
  882
+        return false;
  883
+    }
  884
+
  885
+
  886
+
  887
+}
  888
+
  889
+
  890
+
  891
+
  892
+
1,270  libagl/include/agg.h
... ...
@@ -0,0 +1,1270 @@
  1
+//----------------------------------------------------------------------------
  2
+// Anti-Grain Geometry - Version 2.1 Lite 
  3
+// Copyright (C) 2002-2003 Maxim Shemanarev (McSeem)
  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
+// The author gratefully acknowleges the support of David Turner, 
  11
+// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType 
  12
+// libray - in producing this work. See http://www.freetype.org for details.
  13
+//
  14
+//----------------------------------------------------------------------------
  15
+// Contact: mcseem@antigrain.com
  16
+//          mcseemagg@yahoo.com
  17
+//          http://www.antigrain.com
  18
+//----------------------------------------------------------------------------
  19
+#ifndef AGG_INCLUDED
  20
+#define AGG_INCLUDED
  21
+
  22
+#include <string.h>
  23
+
  24
+namespace agg
  25
+{
  26
+    //------------------------------------------------------------------------
  27
+    typedef signed char    int8;
  28
+    typedef unsigned char  int8u;
  29
+    typedef signed short   int16;
  30
+    typedef unsigned short int16u;
  31
+    typedef signed int     int32;
  32
+    typedef unsigned int   int32u;
  33
+
  34
+
  35
+
  36
+    //========================================================================
  37
+    struct rgba8 
  38
+    {
  39
+        enum order { rgb, bgr };
  40
+
  41
+        int8u r;
  42
+        int8u g;
  43
+        int8u b;
  44
+        int8u a;
  45
+
  46
+        //--------------------------------------------------------------------
  47
+        rgba8() {}
  48
+
  49
+        //--------------------------------------------------------------------
  50
+        rgba8(unsigned r_, unsigned g_, unsigned b_, unsigned a_=255) :
  51
+            r(int8u(r_)), g(int8u(g_)), b(int8u(b_)), a(int8u(a_)) {}
  52
+
  53
+        //--------------------------------------------------------------------
  54
+        rgba8(unsigned packed, order o) : 
  55
+            r((o == rgb) ? ((packed >> 16) & 0xFF) : (packed & 0xFF)),
  56
+            g((packed >> 8)  & 0xFF),
  57
+            b((o == rgb) ? (packed & 0xFF) : ((packed >> 16) & 0xFF)),
  58
+            a(255) {}
  59
+
  60
+        //--------------------------------------------------------------------
  61
+        void opacity(double a_)
  62
+        {
  63
+            if(a_ < 0.0) a_ = 0.0;
  64
+            if(a_ > 1.0) a_ = 1.0;
  65
+            a = int8u(a_ * 255.0);
  66
+        }
  67
+
  68
+        //--------------------------------------------------------------------
  69
+        double opacity() const
  70
+        {
  71
+            return double(a) / 255.0;
  72
+        }
  73
+
  74
+        //--------------------------------------------------------------------
  75
+        rgba8 gradient(rgba8 c, double k) const
  76
+        {
  77
+            rgba8 ret;
  78
+            int ik = int(k * 256);
  79
+            ret.r = int8u(int(r) + (((int(c.r) - int(r)) * ik) >> 8));
  80
+            ret.g = int8u(int(g) + (((int(c.g) - int(g)) * ik) >> 8));
  81
+            ret.b = int8u(int(b) + (((int(c.b) - int(b)) * ik) >> 8));
  82
+            ret.a = int8u(int(a) + (((int(c.a) - int(a)) * ik) >> 8));
  83
+            return ret;
  84
+        }
  85
+
  86
+        rgba8 pre() const
  87
+        {
  88
+            return rgba8((r*a) >> 8, (g*a) >> 8, (b*a) >> 8, a);
  89
+        }
  90
+    };
  91
+
  92
+
  93
+    //========================================================================
  94
+    // Rendering buffer wrapper. This class does not know anything about 
  95
+    // memory organizations, all it does it keeps an array of pointers 
  96
+    // to each pixel row. The general rules of rendering are as follows.
  97
+    // 
  98
+    // 1. Allocate or create somehow a rendering buffer itself. Since 
  99
+    //    the library does not depend on any particular platform or
  100
+    //    architecture it was decided that it's your responsibility 
  101
+    //    to create and destroy rendering buffers properly. You can use
  102
+    //    any available mechanism to create it - you can use a system API 
  103
+    //    function, simple memory allocation, or even statically defined array. 
  104
+    //    You also should know the memory organization (or possible variants)
  105
+    //    in your system. For example, there's an R,G,B or B,G,R organizations 
  106
+    //    with one byte per component (three byter per pixel) is used very often. 
  107
+    //    So, if you intend to use class render_bgr24, for example, you should 
  108
+    //    allocate at least width*height*3 bytes of memory.
  109
+    //
  110
+    // 2. Create a rendering_buffer object and then call method attach(). It requires
  111
+    //    a pointer to the buffer itself, width and height of the buffer in 
  112
+    //    pixels, and the length of the row in bytes. All these values must 
  113
+    //    properly correspond to the memory organization. The argument stride
  114
+    //    is used because in reality the row length in bytes does not obligatory 
  115
+    //    correspond with the width of the image in pixels, i.e. it cannot be 
  116
+    //    simply calculated as width_in_pixels * bytes_per_pixel. For example, 
  117
+    //    it must be aligned to 4 bytes in Windows bitmaps. Besides, the value
  118
+    //    of stride can be negative - it depends on the order of displaying
  119
+    //    the rendering buffer - from top to bottom or from bottom to top. 
  120
+    //    In other words, if stride > 0 the pointers to each row will start 
  121
+    //    from the beginning of the buffer and increase. If it < 0, the pointers 
  122
+    //    start from the end of the buffer and decrease. It gives you an 
  123
+    //    additional degree of freedom.
  124
+    //    Method attach() can be called more than once. The execution time of it
  125
+    //    is very little, still it allocates memory of heigh * sizeof(char*) bytes
  126
+    //    and has a loop while(height--) {...}, so it's unreasonable to call it
  127
+    //    every time before drawing any single pixel :-)
  128
+    //
  129
+    // 3. Create an object (or a number of objects) of a rendering class, such as
  130
+    //    renderer_bgr24_solid, renderer_bgr24_image and so on. These classes
  131
+    //    require a pointer to the renderer_buffer object, but they do not perform
  132
+    //    any considerable operations except storing this pointer. So, rendering
  133
+    //    objects can be created on demand almost any time. These objects know 
  134
+    //    about concrete memory organization (this knowledge is hardcoded), so 
  135
+    //    actually, the memory you allocated or created in clause 1 should 
  136
+    //    actually be in correspondence to the needs of the rendering class.
  137
+    //  
  138
+    // 4. Rener your image using rendering classes, for example, rasterizer
  139
+    //  
  140
+    // 5. Display the result, or store it, or whatever. It's also your 
  141
+    //    responsibility and depends on the platform.
  142
+    //------------------------------------------------------------------------
  143
+    class rendering_buffer
  144
+    {
  145
+    public:
  146
+        ~rendering_buffer();
  147
+
  148
+        //-----------------------------------------Initialization
  149
+        rendering_buffer(unsigned char* buf,
  150
+                         unsigned width, 
  151
+                         unsigned height,
  152
+                         int      stride);
  153
+
  154
+        //-----------------------------------------Initialization
  155
+        void attach(unsigned char* buf,
  156
+                    unsigned width, 
  157
+                    unsigned height,
  158
+                    int      stride);
  159
+
  160
+        //-----------------------------------------Acessors
  161
+        const unsigned char* buf()    const { return m_buf;    }
  162
+        unsigned             width()  const { return m_width;  }
  163
+        unsigned             height() const { return m_height; }
  164
+        int                  stride() const { return m_stride; }
  165
+
  166
+        bool inbox(int x, int y) const
  167
+        {
  168
+            return x >= 0 && y >= 0 && x < int(m_width) && y < int(m_height);
  169
+        }
  170
+        
  171
+        unsigned abs_stride() const 
  172
+        { 
  173
+            return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride); 
  174
+        }
  175
+
  176
+        unsigned char* row(unsigned y) { return m_rows[y];  }
  177
+        const unsigned char* row(unsigned y) const { return m_rows[y]; }
  178
+        
  179
+    private:
  180
+        rendering_buffer(const rendering_buffer&);
  181
+        const rendering_buffer& operator = (const rendering_buffer&);
  182
+
  183
+    private:
  184
+        unsigned char*  m_buf;        // Pointer to renrdering buffer
  185
+        unsigned char** m_rows;       // Pointers to each row of the buffer
  186
+        unsigned        m_width;      // Width in pixels
  187
+        unsigned        m_height;     // Height in pixels
  188
+        int             m_stride;     // Number of bytes per row. Can be < 0
  189
+        unsigned        m_max_height; // Maximal current height
  190
+    };
  191
+
  192
+
  193
+
  194
+    //========================================================================
  195
+    //
  196
+    // This class is used to transfer data from class outline (or a similar one)
  197
+    // to the rendering buffer. It's organized very simple. The class stores 
  198
+    // information of horizontal spans to render it into a pixel-map buffer. 
  199
+    // Each span has initial X, length, and an array of bytes that determine the 
  200
+    // alpha-values for each pixel. So, the restriction of using this class is 256 
  201
+    // levels of Anti-Aliasing, which is quite enough for any practical purpose.
  202
+    // Before using this class you should know the minimal and maximal pixel 
  203
+    // coordinates of your scanline. The protocol of using is:
  204
+    // 1. reset(min_x, max_x)
  205
+    // 2. add_cell() / add_span() - accumulate scanline. You pass Y-coordinate 
  206
+    //    into these functions in order to make scanline know the last Y. Before 
  207
+    //    calling add_cell() / add_span() you should check with method is_ready(y)
  208
+    //    if the last Y has changed. It also checks if the scanline is not empty. 
  209
+    //    When forming one scanline the next X coordinate must be always greater
  210
+    //    than the last stored one, i.e. it works only with ordered coordinates.
  211
+    // 3. If the current scanline is_ready() you should render it and then call 
  212
+    //    reset_spans() before adding new cells/spans.
  213
+    //    
  214
+    // 4. Rendering:
  215
+    // 
  216
+    // Scanline provides an iterator class that allows you to extract
  217
+    // the spans and the cover values for each pixel. Be aware that clipping
  218
+    // has not been done yet, so you should perform it yourself.
  219
+    // Use scanline::iterator to render spans:
  220
+    //-------------------------------------------------------------------------
  221
+    //
  222
+    // int base_x = sl.base_x();          // base X. Should be added to the span's X
  223
+    //                                    // "sl" is a const reference to the 
  224
+    //                                    // scanline passed in.
  225
+    //
  226
+    // int y = sl.y();                    // Y-coordinate of the scanline
  227
+    //
  228
+    // ************************************
  229
+    // ...Perform vertical clipping here...
  230
+    // ************************************
  231
+    //
  232
+    // scanline::iterator span(sl);
  233
+    // 
  234
+    // unsigned char* row = m_rbuf->row(y); // The the address of the beginning 
  235
+    //                                      // of the current row
  236
+    // 
  237
+    // unsigned num_spans = sl.num_spans(); // Number of spans. It's guaranteed that
  238
+    //                                      // num_spans is always greater than 0.
  239
+    //
  240
+    // do
  241
+    // {
  242
+    //     int x = span.next() + base_x;        // The beginning X of the span
  243
+    //
  244
+    //     const int8u covers* = span.covers(); // The array of the cover values
  245
+    //
  246
+    //     int num_pix = span.num_pix();        // Number of pixels of the span.
  247
+    //                                          // Always greater than 0, still we
  248
+    //                                          // shoud use "int" instead of 
  249
+    //                                          // "unsigned" because it's more
  250
+    //                                          // convenient for clipping
  251
+    //
  252
+    //     **************************************
  253
+    //     ...Perform horizontal clipping here...
  254
+    //     ...you have x, covers, and pix_count..
  255
+    //     **************************************
  256
+    //
  257
+    //     unsigned char* dst = row + x;  // Calculate the start address of the row.
  258
+    //                                    // In this case we assume a simple 
  259
+    //                                    // grayscale image 1-byte per pixel.
  260
+    //     do
  261
+    //     {
  262
+    //         *dst++ = *covers++;        // Hypotetical rendering. 
  263
+    //     }
  264
+    //     while(--num_pix);
  265
+    // } 
  266
+    // while(--num_spans);  // num_spans cannot be 0, so this loop is quite safe
  267
+    //------------------------------------------------------------------------
  268
+    //
  269
+    // The question is: why should we accumulate the whole scanline when we
  270
+    // could render just separate spans when they're ready?
  271
+    // That's because using the scaline is in general faster. When is consists 
  272
+    // of more than one span the conditions for the processor cash system
  273
+    // are better, because switching between two different areas of memory 
  274
+    // (that can be large ones) occures less frequently.
  275
+    //------------------------------------------------------------------------
  276
+    class scanline
  277
+    {
  278
+    public:
  279
+        enum { aa_shift = 8 };
  280
+
  281
+        class iterator
  282
+        {
  283
+        public:
  284
+            iterator(const scanline& sl) :
  285
+                m_covers(sl.m_covers),
  286
+                m_cur_count(sl.m_counts),
  287
+                m_cur_start_ptr(sl.m_start_ptrs)
  288
+            {
  289
+            }
  290
+
  291
+            int next()
  292
+            {
  293
+                ++m_cur_count;
  294
+                ++m_cur_start_ptr;
  295
+                return int(*m_cur_start_ptr - m_covers);
  296
+            }
  297
+
  298
+            int num_pix() const { return int(*m_cur_count); }
  299
+            const int8u* covers() const { return *m_cur_start_ptr; }
  300
+
  301
+        private:
  302
+            const int8u*        m_covers;
  303
+            const int16u*       m_cur_count;
  304
+            const int8u* const* m_cur_start_ptr;
  305
+        };
  306
+
  307
+        friend class iterator;
  308
+
  309
+        ~scanline();
  310
+        scanline();
  311
+
  312
+        void     reset(int min_x, int max_x, int dx=0, int dy=0);
  313
+
  314
+        void     reset_spans();
  315
+        void     add_cell(int x, int y, unsigned cover);
  316
+        void     add_span(int x, int y, unsigned len, unsigned cover);
  317
+        int      is_ready(int y) const;
  318
+        int      base_x()    const { return m_min_x + m_dx;  }
  319
+        int      y()         const { return m_last_y + m_dy; }
  320
+        unsigned num_spans() const { return m_num_spans;     }
  321
+
  322
+    private:
  323
+        scanline(const scanline&);
  324
+        const scanline& operator = (const scanline&);
  325
+
  326
+    private:
  327
+        int      m_min_x;
  328
+        unsigned m_max_len;
  329
+        int      m_dx;
  330
+        int      m_dy;
  331
+        int      m_last_x;
  332
+        int      m_last_y;
  333
+        int8u*   m_covers;
  334
+        int8u**  m_start_ptrs;
  335
+        int16u*  m_counts;
  336
+        unsigned m_num_spans;
  337
+        int8u**  m_cur_start_ptr;
  338
+        int16u*  m_cur_count;
  339
+    };
  340
+
  341
+
  342
+    //------------------------------------------------------------------------
  343
+    inline void scanline::reset_spans()
  344
+    {
  345
+        m_last_x        = 0x7FFF;
  346
+        m_last_y        = 0x7FFF;
  347
+        m_cur_count     = m_counts;
  348
+        m_cur_start_ptr = m_start_ptrs;
  349
+        m_num_spans     = 0;
  350
+    }
  351
+
  352
+
  353
+    //------------------------------------------------------------------------
  354
+    inline void scanline::add_cell(int x, int y, unsigned cover)
  355
+    {
  356
+        x -= m_min_x;
  357
+        m_covers[x] = (unsigned char)cover;
  358
+        if(x == m_last_x+1)
  359
+        {
  360
+            (*m_cur_count)++;
  361
+        }
  362
+        else
  363
+        {
  364
+            *++m_cur_count = 1;
  365
+            *++m_cur_start_ptr = m_covers + x;
  366
+            m_num_spans++;
  367
+        }
  368
+        m_last_x = x;
  369
+        m_last_y = y;
  370
+    }
  371
+
  372
+
  373
+    //------------------------------------------------------------------------
  374
+    inline int scanline::is_ready(int y) const
  375
+    {
  376
+        return m_num_spans && (y ^ m_last_y);
  377
+    }
  378
+
  379
+
  380
+
  381
+
  382
+    //========================================================================
  383
+    // This class template is used basically for rendering scanlines. 
  384
+    // The 'Span' argument is one of the span renderers, such as span_rgb24 
  385
+    // and others.
  386
+    // 
  387
+    // Usage:
  388
+    // 
  389
+    //     // Creation
  390
+    //     agg::rendering_buffer rbuf(ptr, w, h, stride);
  391
+    //     agg::renderer<agg::span_rgb24> ren(rbuf);
  392
+    //     agg::rasterizer ras;
  393
+    //
  394
+    //     // Clear the frame buffer
  395
+    //     ren.clear(agg::rgba8(0,0,0));
  396
+    //
  397
+    //     // Making polygon
  398
+    //     // ras.move_to(. . .);
  399
+    //     // ras.line_to(. . .);
  400
+    //     // . . .
  401
+    //
  402
+    //     // Rendering
  403
+    //     ras.render(ren, agg::rgba8(200, 100, 80));
  404
+    //  
  405
+    //------------------------------------------------------------------------
  406
+    template<class Span> class renderer
  407
+    {
  408
+    public:
  409
+        //--------------------------------------------------------------------
  410
+        renderer(rendering_buffer& rbuf) : m_rbuf(&rbuf)
  411
+        {
  412
+        }
  413
+        
  414
+        //--------------------------------------------------------------------
  415
+        void clear(const rgba8& c)
  416
+        {
  417
+            unsigned y;
  418
+            for(y = 0; y < m_rbuf->height(); y++)
  419
+            {
  420
+                m_span.hline(m_rbuf->row(y), 0, m_rbuf->width(), c);
  421
+            }
  422
+        }
  423
+
  424
+        //--------------------------------------------------------------------
  425
+        void pixel(int x, int y, const rgba8& c)
  426
+        {
  427
+            if(m_rbuf->inbox(x, y))
  428
+            {
  429
+                m_span.hline(m_rbuf->row(y), x, 1, c);
  430
+            }
  431
+        }
  432
+
  433
+        //--------------------------------------------------------------------
  434
+        rgba8 pixel(int x, int y) const
  435
+        {
  436
+            if(m_rbuf->inbox(x, y))
  437
+            {
  438
+                return m_span.get(m_rbuf->row(y), x);
  439
+            }
  440
+            return rgba8(0,0,0);
  441
+        }
  442
+
  443
+        //--------------------------------------------------------------------
  444
+        void render(const scanline& sl, const rgba8& c)
  445
+        {
  446
+            if(sl.y() < 0 || sl.y() >= int(m_rbuf->height()))
  447
+            {
  448
+                return;
  449
+            }
  450
+
  451
+            unsigned num_spans = sl.num_spans();
  452
+            int base_x = sl.base_x();
  453
+            unsigned char* row = m_rbuf->row(sl.y());
  454
+            scanline::iterator span(sl);
  455
+
  456
+            do
  457
+            {
  458
+                int x = span.next() + base_x;
  459
+                const int8u* covers = span.covers();
  460
+                int num_pix = span.num_pix();
  461
+                if(x < 0)
  462
+                {
  463
+                    num_pix += x;
  464
+                    if(num_pix <= 0) continue;
  465
+                    covers -= x;
  466
+                    x = 0;
  467
+                }
  468
+                if(x + num_pix >= int(m_rbuf->width()))
  469
+                {
  470
+                    num_pix = m_rbuf->width() - x;
  471
+                    if(num_pix <= 0) continue;
  472
+                }
  473
+                m_span.render(row, x, num_pix, covers, c);
  474
+            }
  475
+            while(--num_spans);
  476
+        }
  477
+
  478
+        //--------------------------------------------------------------------
  479
+        rendering_buffer& rbuf() { return *m_rbuf; }
  480
+
  481
+    private:
  482
+        rendering_buffer* m_rbuf;
  483
+        Span              m_span;
  484
+    };
  485
+
  486
+
  487
+    //------------------------------------------------------------------------
  488
+    // These constants determine the subpixel accuracy, to be more precise, 
  489
+    // the number of bits of the fractional part of the coordinates. 
  490
+    // The possible coordinate capacity in bits can be calculated by formula:
  491
+    // sizeof(int) * 8 - poly_base_shift * 2, i.e, for 32-bit integers and
  492
+    // 8-bits fractional part the capacity is 16 bits or [-32768...32767].
  493
+    enum
  494
+    {
  495
+        poly_base_shift = 8,
  496
+        poly_base_size  = 1 << poly_base_shift,
  497
+        poly_base_mask  = poly_base_size - 1
  498
+    };
  499
+    
  500
+    //------------------------------------------------------------------------
  501
+    inline int poly_coord(double c)
  502
+    {
  503
+        return int(c * poly_base_size);
  504
+    }
  505
+
  506
+    //------------------------------------------------------------------------
  507
+    // A pixel cell. There're no constructors defined and it was done 
  508
+    // intentionally in order to avoid extra overhead when allocating an 
  509
+    // array of cells.
  510
+    struct cell
  511
+    {
  512
+        int16 x;
  513
+        int16 y;
  514
+        int   packed_coord;
  515
+        int   cover;
  516
+        int   area;
  517
+
  518
+        void set(int x, int y, int c, int a);
  519
+        void set_coord(int x, int y);
  520
+        void set_cover(int c, int a);
  521
+        void add_cover(int c, int a);
  522
+    };
  523
+
  524
+
  525
+    //------------------------------------------------------------------------
  526
+    // An internal class that implements the main rasterization algorithm.
  527
+    // Used in the rasterizer. Should not be used direcly.
  528
+    class outline
  529
+    {
  530
+        enum
  531
+        {
  532
+            cell_block_shift = 12,
  533
+            cell_block_size  = 1 << cell_block_shift,
  534
+            cell_block_mask  = cell_block_size - 1,
  535
+            cell_block_pool  = 256,
  536
+            cell_block_limit = 1024
  537
+        };
  538
+
  539
+    public:
  540
+
  541
+        ~outline();
  542
+        outline();
  543
+
  544
+        void reset();
  545
+
  546
+        void move_to(int x, int y);
  547
+        void line_to(int x, int y);
  548
+
  549
+        int min_x() const { return m_min_x; }
  550
+        int min_y() const { return m_min_y; }
  551
+        int max_x() const { return m_max_x; }
  552
+        int max_y() const { return m_max_y; }
  553
+
  554
+        unsigned num_cells() const {return m_num_cells; }
  555
+        const cell* const* cells();
  556
+
  557
+    private:
  558
+        outline(const outline&);
  559
+        const outline& operator = (const outline&);
  560
+
  561
+        void set_cur_cell(int x, int y);
  562
+        void add_cur_cell();
  563
+        void sort_cells();
  564
+        void render_scanline(int ey, int x1, int y1, int x2, int y2);
  565
+        void render_line(int x1, int y1, int x2, int y2);
  566
+        void allocate_block();
  567
+        
  568
+        static void qsort_cells(cell** start, unsigned num);
  569
+
  570
+    private:
  571
+        unsigned  m_num_blocks;
  572
+        unsigned  m_max_blocks;
  573
+        unsigned  m_cur_block;
  574
+        unsigned  m_num_cells;
  575
+        cell**    m_cells;
  576
+        cell*     m_cur_cell_ptr;
  577
+        cell**    m_sorted_cells;
  578
+        unsigned  m_sorted_size;
  579
+        cell      m_cur_cell;
  580
+        int       m_cur_x;
  581
+        int       m_cur_y;
  582
+        int       m_close_x;
  583
+        int       m_close_y;
  584
+        int       m_min_x;
  585
+        int       m_min_y;
  586
+        int       m_max_x;