You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
855 lines
34 KiB
855 lines
34 KiB
//---------------------------------------------------------------------------- |
|
// Anti-Grain Geometry - Version 2.4 |
|
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) |
|
// |
|
// Permission to copy, use, modify, sell and distribute this software |
|
// is granted provided this copyright notice appears in all copies. |
|
// This software is provided "as is" without express or implied |
|
// warranty, and with no claim as to its suitability for any purpose. |
|
// |
|
//---------------------------------------------------------------------------- |
|
// Contact: mcseem@antigrain.com |
|
// mcseemagg@yahoo.com |
|
// http://www.antigrain.com |
|
//---------------------------------------------------------------------------- |
|
|
|
#ifndef AGG_RENDERER_SCANLINE_INCLUDED |
|
#define AGG_RENDERER_SCANLINE_INCLUDED |
|
|
|
#include <limits> |
|
#include <cstdlib> |
|
#include <cstring> |
|
#include "agg_basics.h" |
|
#include "agg_renderer_base.h" |
|
|
|
namespace agg |
|
{ |
|
|
|
//================================================render_scanline_aa_solid |
|
template<class Scanline, class BaseRenderer, class ColorT> |
|
void render_scanline_aa_solid(const Scanline& sl, |
|
BaseRenderer& ren, |
|
const ColorT& color) |
|
{ |
|
int y = sl.y(); |
|
unsigned num_spans = sl.num_spans(); |
|
typename Scanline::const_iterator span = sl.begin(); |
|
|
|
for(;;) |
|
{ |
|
int x = span->x; |
|
if(span->len > 0) |
|
{ |
|
ren.blend_solid_hspan(x, y, (unsigned)span->len, |
|
color, |
|
span->covers); |
|
} |
|
else |
|
{ |
|
ren.blend_hline(x, y, (unsigned)(x - span->len - 1), |
|
color, |
|
*(span->covers)); |
|
} |
|
if(--num_spans == 0) break; |
|
++span; |
|
} |
|
} |
|
|
|
//===============================================render_scanlines_aa_solid |
|
template<class Rasterizer, class Scanline, |
|
class BaseRenderer, class ColorT> |
|
void render_scanlines_aa_solid(Rasterizer& ras, Scanline& sl, |
|
BaseRenderer& ren, const ColorT& color) |
|
{ |
|
if(ras.rewind_scanlines()) |
|
{ |
|
// Explicitly convert "color" to the BaseRenderer color type. |
|
// For example, it can be called with color type "rgba", while |
|
// "rgba8" is needed. Otherwise it will be implicitly |
|
// converted in the loop many times. |
|
//---------------------- |
|
typename BaseRenderer::color_type ren_color = color; |
|
|
|
sl.reset(ras.min_x(), ras.max_x()); |
|
while(ras.sweep_scanline(sl)) |
|
{ |
|
//render_scanline_aa_solid(sl, ren, ren_color); |
|
|
|
// This code is equivalent to the above call (copy/paste). |
|
// It's just a "manual" optimization for old compilers, |
|
// like Microsoft Visual C++ v6.0 |
|
//------------------------------- |
|
int y = sl.y(); |
|
unsigned num_spans = sl.num_spans(); |
|
typename Scanline::const_iterator span = sl.begin(); |
|
|
|
for(;;) |
|
{ |
|
int x = span->x; |
|
if(span->len > 0) |
|
{ |
|
ren.blend_solid_hspan(x, y, (unsigned)span->len, |
|
ren_color, |
|
span->covers); |
|
} |
|
else |
|
{ |
|
ren.blend_hline(x, y, (unsigned)(x - span->len - 1), |
|
ren_color, |
|
*(span->covers)); |
|
} |
|
if(--num_spans == 0) break; |
|
++span; |
|
} |
|
} |
|
} |
|
} |
|
|
|
//==============================================renderer_scanline_aa_solid |
|
template<class BaseRenderer> class renderer_scanline_aa_solid |
|
{ |
|
public: |
|
typedef BaseRenderer base_ren_type; |
|
typedef typename base_ren_type::color_type color_type; |
|
|
|
//-------------------------------------------------------------------- |
|
renderer_scanline_aa_solid() : m_ren(0) {} |
|
explicit renderer_scanline_aa_solid(base_ren_type& ren) : m_ren(&ren) {} |
|
void attach(base_ren_type& ren) |
|
{ |
|
m_ren = &ren; |
|
} |
|
|
|
//-------------------------------------------------------------------- |
|
void color(const color_type& c) { m_color = c; } |
|
const color_type& color() const { return m_color; } |
|
|
|
//-------------------------------------------------------------------- |
|
void prepare() {} |
|
|
|
//-------------------------------------------------------------------- |
|
template<class Scanline> void render(const Scanline& sl) |
|
{ |
|
render_scanline_aa_solid(sl, *m_ren, m_color); |
|
} |
|
|
|
private: |
|
base_ren_type* m_ren; |
|
color_type m_color; |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//======================================================render_scanline_aa |
|
template<class Scanline, class BaseRenderer, |
|
class SpanAllocator, class SpanGenerator> |
|
void render_scanline_aa(const Scanline& sl, BaseRenderer& ren, |
|
SpanAllocator& alloc, SpanGenerator& span_gen) |
|
{ |
|
int y = sl.y(); |
|
|
|
unsigned num_spans = sl.num_spans(); |
|
typename Scanline::const_iterator span = sl.begin(); |
|
for(;;) |
|
{ |
|
int x = span->x; |
|
int len = span->len; |
|
const typename Scanline::cover_type* covers = span->covers; |
|
|
|
if(len < 0) len = -len; |
|
typename BaseRenderer::color_type* colors = alloc.allocate(len); |
|
span_gen.generate(colors, x, y, len); |
|
ren.blend_color_hspan(x, y, len, colors, |
|
(span->len < 0) ? 0 : covers, *covers); |
|
|
|
if(--num_spans == 0) break; |
|
++span; |
|
} |
|
} |
|
|
|
//=====================================================render_scanlines_aa |
|
template<class Rasterizer, class Scanline, class BaseRenderer, |
|
class SpanAllocator, class SpanGenerator> |
|
void render_scanlines_aa(Rasterizer& ras, Scanline& sl, BaseRenderer& ren, |
|
SpanAllocator& alloc, SpanGenerator& span_gen) |
|
{ |
|
if(ras.rewind_scanlines()) |
|
{ |
|
sl.reset(ras.min_x(), ras.max_x()); |
|
span_gen.prepare(); |
|
while(ras.sweep_scanline(sl)) |
|
{ |
|
render_scanline_aa(sl, ren, alloc, span_gen); |
|
} |
|
} |
|
} |
|
|
|
//====================================================renderer_scanline_aa |
|
template<class BaseRenderer, class SpanAllocator, class SpanGenerator> |
|
class renderer_scanline_aa |
|
{ |
|
public: |
|
typedef BaseRenderer base_ren_type; |
|
typedef SpanAllocator alloc_type; |
|
typedef SpanGenerator span_gen_type; |
|
|
|
//-------------------------------------------------------------------- |
|
renderer_scanline_aa() : m_ren(0), m_alloc(0), m_span_gen(0) {} |
|
renderer_scanline_aa(base_ren_type& ren, |
|
alloc_type& alloc, |
|
span_gen_type& span_gen) : |
|
m_ren(&ren), |
|
m_alloc(&alloc), |
|
m_span_gen(&span_gen) |
|
{} |
|
void attach(base_ren_type& ren, |
|
alloc_type& alloc, |
|
span_gen_type& span_gen) |
|
{ |
|
m_ren = &ren; |
|
m_alloc = &alloc; |
|
m_span_gen = &span_gen; |
|
} |
|
|
|
//-------------------------------------------------------------------- |
|
void prepare() { m_span_gen->prepare(); } |
|
|
|
//-------------------------------------------------------------------- |
|
template<class Scanline> void render(const Scanline& sl) |
|
{ |
|
render_scanline_aa(sl, *m_ren, *m_alloc, *m_span_gen); |
|
} |
|
|
|
private: |
|
base_ren_type* m_ren; |
|
alloc_type* m_alloc; |
|
span_gen_type* m_span_gen; |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
//===============================================render_scanline_bin_solid |
|
template<class Scanline, class BaseRenderer, class ColorT> |
|
void render_scanline_bin_solid(const Scanline& sl, |
|
BaseRenderer& ren, |
|
const ColorT& color) |
|
{ |
|
unsigned num_spans = sl.num_spans(); |
|
typename Scanline::const_iterator span = sl.begin(); |
|
for(;;) |
|
{ |
|
ren.blend_hline(span->x, |
|
sl.y(), |
|
span->x - 1 + ((span->len < 0) ? |
|
-span->len : |
|
span->len), |
|
color, |
|
cover_full); |
|
if(--num_spans == 0) break; |
|
++span; |
|
} |
|
} |
|
|
|
//==============================================render_scanlines_bin_solid |
|
template<class Rasterizer, class Scanline, |
|
class BaseRenderer, class ColorT> |
|
void render_scanlines_bin_solid(Rasterizer& ras, Scanline& sl, |
|
BaseRenderer& ren, const ColorT& color) |
|
{ |
|
if(ras.rewind_scanlines()) |
|
{ |
|
// Explicitly convert "color" to the BaseRenderer color type. |
|
// For example, it can be called with color type "rgba", while |
|
// "rgba8" is needed. Otherwise it will be implicitly |
|
// converted in the loop many times. |
|
//---------------------- |
|
typename BaseRenderer::color_type ren_color(color); |
|
|
|
sl.reset(ras.min_x(), ras.max_x()); |
|
while(ras.sweep_scanline(sl)) |
|
{ |
|
//render_scanline_bin_solid(sl, ren, ren_color); |
|
|
|
// This code is equivalent to the above call (copy/paste). |
|
// It's just a "manual" optimization for old compilers, |
|
// like Microsoft Visual C++ v6.0 |
|
//------------------------------- |
|
unsigned num_spans = sl.num_spans(); |
|
typename Scanline::const_iterator span = sl.begin(); |
|
for(;;) |
|
{ |
|
ren.blend_hline(span->x, |
|
sl.y(), |
|
span->x - 1 + ((span->len < 0) ? |
|
-span->len : |
|
span->len), |
|
ren_color, |
|
cover_full); |
|
if(--num_spans == 0) break; |
|
++span; |
|
} |
|
} |
|
} |
|
} |
|
|
|
//=============================================renderer_scanline_bin_solid |
|
template<class BaseRenderer> class renderer_scanline_bin_solid |
|
{ |
|
public: |
|
typedef BaseRenderer base_ren_type; |
|
typedef typename base_ren_type::color_type color_type; |
|
|
|
//-------------------------------------------------------------------- |
|
renderer_scanline_bin_solid() : m_ren(0) {} |
|
explicit renderer_scanline_bin_solid(base_ren_type& ren) : m_ren(&ren) {} |
|
void attach(base_ren_type& ren) |
|
{ |
|
m_ren = &ren; |
|
} |
|
|
|
//-------------------------------------------------------------------- |
|
void color(const color_type& c) { m_color = c; } |
|
const color_type& color() const { return m_color; } |
|
|
|
//-------------------------------------------------------------------- |
|
void prepare() {} |
|
|
|
//-------------------------------------------------------------------- |
|
template<class Scanline> void render(const Scanline& sl) |
|
{ |
|
render_scanline_bin_solid(sl, *m_ren, m_color); |
|
} |
|
|
|
private: |
|
base_ren_type* m_ren; |
|
color_type m_color; |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//======================================================render_scanline_bin |
|
template<class Scanline, class BaseRenderer, |
|
class SpanAllocator, class SpanGenerator> |
|
void render_scanline_bin(const Scanline& sl, BaseRenderer& ren, |
|
SpanAllocator& alloc, SpanGenerator& span_gen) |
|
{ |
|
int y = sl.y(); |
|
|
|
unsigned num_spans = sl.num_spans(); |
|
typename Scanline::const_iterator span = sl.begin(); |
|
for(;;) |
|
{ |
|
int x = span->x; |
|
int len = span->len; |
|
if(len < 0) len = -len; |
|
typename BaseRenderer::color_type* colors = alloc.allocate(len); |
|
span_gen.generate(colors, x, y, len); |
|
ren.blend_color_hspan(x, y, len, colors, 0, cover_full); |
|
if(--num_spans == 0) break; |
|
++span; |
|
} |
|
} |
|
|
|
//=====================================================render_scanlines_bin |
|
template<class Rasterizer, class Scanline, class BaseRenderer, |
|
class SpanAllocator, class SpanGenerator> |
|
void render_scanlines_bin(Rasterizer& ras, Scanline& sl, BaseRenderer& ren, |
|
SpanAllocator& alloc, SpanGenerator& span_gen) |
|
{ |
|
if(ras.rewind_scanlines()) |
|
{ |
|
sl.reset(ras.min_x(), ras.max_x()); |
|
span_gen.prepare(); |
|
while(ras.sweep_scanline(sl)) |
|
{ |
|
render_scanline_bin(sl, ren, alloc, span_gen); |
|
} |
|
} |
|
} |
|
|
|
//====================================================renderer_scanline_bin |
|
template<class BaseRenderer, class SpanAllocator, class SpanGenerator> |
|
class renderer_scanline_bin |
|
{ |
|
public: |
|
typedef BaseRenderer base_ren_type; |
|
typedef SpanAllocator alloc_type; |
|
typedef SpanGenerator span_gen_type; |
|
|
|
//-------------------------------------------------------------------- |
|
renderer_scanline_bin() : m_ren(0), m_alloc(0), m_span_gen(0) {} |
|
renderer_scanline_bin(base_ren_type& ren, |
|
alloc_type& alloc, |
|
span_gen_type& span_gen) : |
|
m_ren(&ren), |
|
m_alloc(&alloc), |
|
m_span_gen(&span_gen) |
|
{} |
|
void attach(base_ren_type& ren, |
|
alloc_type& alloc, |
|
span_gen_type& span_gen) |
|
{ |
|
m_ren = &ren; |
|
m_alloc = &alloc; |
|
m_span_gen = &span_gen; |
|
} |
|
|
|
//-------------------------------------------------------------------- |
|
void prepare() { m_span_gen->prepare(); } |
|
|
|
//-------------------------------------------------------------------- |
|
template<class Scanline> void render(const Scanline& sl) |
|
{ |
|
render_scanline_bin(sl, *m_ren, *m_alloc, *m_span_gen); |
|
} |
|
|
|
private: |
|
base_ren_type* m_ren; |
|
alloc_type* m_alloc; |
|
span_gen_type* m_span_gen; |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//========================================================render_scanlines |
|
template<class Rasterizer, class Scanline, class Renderer> |
|
void render_scanlines(Rasterizer& ras, Scanline& sl, Renderer& ren) |
|
{ |
|
if(ras.rewind_scanlines()) |
|
{ |
|
sl.reset(ras.min_x(), ras.max_x()); |
|
ren.prepare(); |
|
while(ras.sweep_scanline(sl)) |
|
{ |
|
ren.render(sl); |
|
} |
|
} |
|
} |
|
|
|
//========================================================render_all_paths |
|
template<class Rasterizer, class Scanline, class Renderer, |
|
class VertexSource, class ColorStorage, class PathId> |
|
void render_all_paths(Rasterizer& ras, |
|
Scanline& sl, |
|
Renderer& r, |
|
VertexSource& vs, |
|
const ColorStorage& as, |
|
const PathId& path_id, |
|
unsigned num_paths) |
|
{ |
|
for(unsigned i = 0; i < num_paths; i++) |
|
{ |
|
ras.reset(); |
|
ras.add_path(vs, path_id[i]); |
|
r.color(as[i]); |
|
render_scanlines(ras, sl, r); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
//=============================================render_scanlines_compound |
|
template<class Rasterizer, |
|
class ScanlineAA, |
|
class ScanlineBin, |
|
class BaseRenderer, |
|
class SpanAllocator, |
|
class StyleHandler> |
|
void render_scanlines_compound(Rasterizer& ras, |
|
ScanlineAA& sl_aa, |
|
ScanlineBin& sl_bin, |
|
BaseRenderer& ren, |
|
SpanAllocator& alloc, |
|
StyleHandler& sh) |
|
{ |
|
if(ras.rewind_scanlines()) |
|
{ |
|
int min_x = ras.min_x(); |
|
int len = ras.max_x() - min_x + 2; |
|
sl_aa.reset(min_x, ras.max_x()); |
|
sl_bin.reset(min_x, ras.max_x()); |
|
|
|
typedef typename BaseRenderer::color_type color_type; |
|
color_type* color_span = alloc.allocate(len * 2); |
|
color_type* mix_buffer = color_span + len; |
|
unsigned num_spans; |
|
|
|
unsigned num_styles; |
|
unsigned style; |
|
bool solid; |
|
while((num_styles = ras.sweep_styles()) > 0) |
|
{ |
|
typename ScanlineAA::const_iterator span_aa; |
|
if(num_styles == 1) |
|
{ |
|
// Optimization for a single style. Happens often |
|
//------------------------- |
|
if(ras.sweep_scanline(sl_aa, 0)) |
|
{ |
|
style = ras.style(0); |
|
if(sh.is_solid(style)) |
|
{ |
|
// Just solid fill |
|
//----------------------- |
|
render_scanline_aa_solid(sl_aa, ren, sh.color(style)); |
|
} |
|
else |
|
{ |
|
// Arbitrary span generator |
|
//----------------------- |
|
span_aa = sl_aa.begin(); |
|
num_spans = sl_aa.num_spans(); |
|
for(;;) |
|
{ |
|
len = span_aa->len; |
|
sh.generate_span(color_span, |
|
span_aa->x, |
|
sl_aa.y(), |
|
len, |
|
style); |
|
|
|
ren.blend_color_hspan(span_aa->x, |
|
sl_aa.y(), |
|
span_aa->len, |
|
color_span, |
|
span_aa->covers); |
|
if(--num_spans == 0) break; |
|
++span_aa; |
|
} |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
if(ras.sweep_scanline(sl_bin, -1)) |
|
{ |
|
// Clear the spans of the mix_buffer |
|
//-------------------- |
|
typename ScanlineBin::const_iterator span_bin = sl_bin.begin(); |
|
num_spans = sl_bin.num_spans(); |
|
for(;;) |
|
{ |
|
std::memset(mix_buffer + span_bin->x - min_x, |
|
0, |
|
span_bin->len * sizeof(color_type)); |
|
|
|
if(--num_spans == 0) break; |
|
++span_bin; |
|
} |
|
|
|
unsigned i; |
|
for(i = 0; i < num_styles; i++) |
|
{ |
|
style = ras.style(i); |
|
solid = sh.is_solid(style); |
|
|
|
if(ras.sweep_scanline(sl_aa, i)) |
|
{ |
|
color_type* colors; |
|
color_type* cspan; |
|
typename ScanlineAA::cover_type* covers; |
|
span_aa = sl_aa.begin(); |
|
num_spans = sl_aa.num_spans(); |
|
if(solid) |
|
{ |
|
// Just solid fill |
|
//----------------------- |
|
for(;;) |
|
{ |
|
color_type c = sh.color(style); |
|
len = span_aa->len; |
|
colors = mix_buffer + span_aa->x - min_x; |
|
covers = span_aa->covers; |
|
do |
|
{ |
|
if(*covers == cover_full) |
|
{ |
|
*colors = c; |
|
} |
|
else |
|
{ |
|
colors->add(c, *covers); |
|
} |
|
++colors; |
|
++covers; |
|
} |
|
while(--len); |
|
if(--num_spans == 0) break; |
|
++span_aa; |
|
} |
|
} |
|
else |
|
{ |
|
// Arbitrary span generator |
|
//----------------------- |
|
for(;;) |
|
{ |
|
len = span_aa->len; |
|
colors = mix_buffer + span_aa->x - min_x; |
|
cspan = color_span; |
|
sh.generate_span(cspan, |
|
span_aa->x, |
|
sl_aa.y(), |
|
len, |
|
style); |
|
covers = span_aa->covers; |
|
do |
|
{ |
|
if(*covers == cover_full) |
|
{ |
|
*colors = *cspan; |
|
} |
|
else |
|
{ |
|
colors->add(*cspan, *covers); |
|
} |
|
++cspan; |
|
++colors; |
|
++covers; |
|
} |
|
while(--len); |
|
if(--num_spans == 0) break; |
|
++span_aa; |
|
} |
|
} |
|
} |
|
} |
|
|
|
// Emit the blended result as a color hspan |
|
//------------------------- |
|
span_bin = sl_bin.begin(); |
|
num_spans = sl_bin.num_spans(); |
|
for(;;) |
|
{ |
|
ren.blend_color_hspan(span_bin->x, |
|
sl_bin.y(), |
|
span_bin->len, |
|
mix_buffer + span_bin->x - min_x, |
|
0, |
|
cover_full); |
|
if(--num_spans == 0) break; |
|
++span_bin; |
|
} |
|
} // if(ras.sweep_scanline(sl_bin, -1)) |
|
} // if(num_styles == 1) ... else |
|
} // while((num_styles = ras.sweep_styles()) > 0) |
|
} // if(ras.rewind_scanlines()) |
|
} |
|
|
|
//=======================================render_scanlines_compound_layered |
|
template<class Rasterizer, |
|
class ScanlineAA, |
|
class BaseRenderer, |
|
class SpanAllocator, |
|
class StyleHandler> |
|
void render_scanlines_compound_layered(Rasterizer& ras, |
|
ScanlineAA& sl_aa, |
|
BaseRenderer& ren, |
|
SpanAllocator& alloc, |
|
StyleHandler& sh) |
|
{ |
|
if(ras.rewind_scanlines()) |
|
{ |
|
int min_x = ras.min_x(); |
|
int len = ras.max_x() - min_x + 2; |
|
sl_aa.reset(min_x, ras.max_x()); |
|
|
|
typedef typename BaseRenderer::color_type color_type; |
|
color_type* color_span = alloc.allocate(len * 2); |
|
color_type* mix_buffer = color_span + len; |
|
cover_type* cover_buffer = ras.allocate_cover_buffer(len); |
|
unsigned num_spans; |
|
|
|
unsigned num_styles; |
|
unsigned style; |
|
bool solid; |
|
while((num_styles = ras.sweep_styles()) > 0) |
|
{ |
|
typename ScanlineAA::const_iterator span_aa; |
|
if(num_styles == 1) |
|
{ |
|
// Optimization for a single style. Happens often |
|
//------------------------- |
|
if(ras.sweep_scanline(sl_aa, 0)) |
|
{ |
|
style = ras.style(0); |
|
if(sh.is_solid(style)) |
|
{ |
|
// Just solid fill |
|
//----------------------- |
|
render_scanline_aa_solid(sl_aa, ren, sh.color(style)); |
|
} |
|
else |
|
{ |
|
// Arbitrary span generator |
|
//----------------------- |
|
span_aa = sl_aa.begin(); |
|
num_spans = sl_aa.num_spans(); |
|
for(;;) |
|
{ |
|
len = span_aa->len; |
|
sh.generate_span(color_span, |
|
span_aa->x, |
|
sl_aa.y(), |
|
len, |
|
style); |
|
|
|
ren.blend_color_hspan(span_aa->x, |
|
sl_aa.y(), |
|
span_aa->len, |
|
color_span, |
|
span_aa->covers); |
|
if(--num_spans == 0) break; |
|
++span_aa; |
|
} |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
int sl_start = ras.scanline_start(); |
|
unsigned sl_len = ras.scanline_length(); |
|
|
|
if(sl_len) |
|
{ |
|
std::memset(mix_buffer + sl_start - min_x, |
|
0, |
|
sl_len * sizeof(color_type)); |
|
|
|
std::memset(cover_buffer + sl_start - min_x, |
|
0, |
|
sl_len * sizeof(cover_type)); |
|
|
|
int sl_y = std::numeric_limits<int>::max(); |
|
unsigned i; |
|
for(i = 0; i < num_styles; i++) |
|
{ |
|
style = ras.style(i); |
|
solid = sh.is_solid(style); |
|
|
|
if(ras.sweep_scanline(sl_aa, i)) |
|
{ |
|
unsigned cover; |
|
color_type* colors; |
|
color_type* cspan; |
|
cover_type* src_covers; |
|
cover_type* dst_covers; |
|
span_aa = sl_aa.begin(); |
|
num_spans = sl_aa.num_spans(); |
|
sl_y = sl_aa.y(); |
|
if(solid) |
|
{ |
|
// Just solid fill |
|
//----------------------- |
|
for(;;) |
|
{ |
|
color_type c = sh.color(style); |
|
len = span_aa->len; |
|
colors = mix_buffer + span_aa->x - min_x; |
|
src_covers = span_aa->covers; |
|
dst_covers = cover_buffer + span_aa->x - min_x; |
|
do |
|
{ |
|
cover = *src_covers; |
|
if(*dst_covers + cover > cover_full) |
|
{ |
|
cover = cover_full - *dst_covers; |
|
} |
|
if(cover) |
|
{ |
|
colors->add(c, cover); |
|
*dst_covers += cover; |
|
} |
|
++colors; |
|
++src_covers; |
|
++dst_covers; |
|
} |
|
while(--len); |
|
if(--num_spans == 0) break; |
|
++span_aa; |
|
} |
|
} |
|
else |
|
{ |
|
// Arbitrary span generator |
|
//----------------------- |
|
for(;;) |
|
{ |
|
len = span_aa->len; |
|
colors = mix_buffer + span_aa->x - min_x; |
|
cspan = color_span; |
|
sh.generate_span(cspan, |
|
span_aa->x, |
|
sl_aa.y(), |
|
len, |
|
style); |
|
src_covers = span_aa->covers; |
|
dst_covers = cover_buffer + span_aa->x - min_x; |
|
do |
|
{ |
|
cover = *src_covers; |
|
if(*dst_covers + cover > cover_full) |
|
{ |
|
cover = cover_full - *dst_covers; |
|
} |
|
if(cover) |
|
{ |
|
colors->add(*cspan, cover); |
|
*dst_covers += cover; |
|
} |
|
++cspan; |
|
++colors; |
|
++src_covers; |
|
++dst_covers; |
|
} |
|
while(--len); |
|
if(--num_spans == 0) break; |
|
++span_aa; |
|
} |
|
} |
|
} |
|
} |
|
ren.blend_color_hspan(sl_start, |
|
sl_y, |
|
sl_len, |
|
mix_buffer + sl_start - min_x, |
|
0, |
|
cover_full); |
|
} //if(sl_len) |
|
} //if(num_styles == 1) ... else |
|
} //while((num_styles = ras.sweep_styles()) > 0) |
|
} //if(ras.rewind_scanlines()) |
|
} |
|
|
|
|
|
} |
|
|
|
#endif
|
|
|