/*
* Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>.
* Copyright 2008, Stephan Aßmus <superstippi@gmx.de>.
* All rights reserved. Distributed under the terms of the MIT License.
*
* Copyright 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
*
*
* Class scanline_p8_subpix_avrg_filtering, a slightly modified version of
* scanline_p8 customized to store 3 covers per pixel and to implement
* average-based color filtering
*
*/
#ifndef AGG_SCANLINE_P_SUBPIX_AVRG_FILTERING_INCLUDED
#define AGG_SCANLINE_P_SUBPIX_AVRG_FILTERING_INCLUDED
#include "GlobalSubpixelSettings.h"
namespace agg
{
//========================================scanline_p8_subpix_avrg_filtering
//
// This is a general purpose scaline container which supports the interface
// used in the rasterizer::render(). See description of scanline_u8
// for details.
//
//------------------------------------------------------------------------
class scanline_p8_subpix_avrg_filtering
{
public:
typedef scanline_p8_subpix self_type;
typedef int8u cover_type;
typedef int16 coord_type;
//--------------------------------------------------------------------
struct span
{
coord_type x;
coord_type len; // If negative, it's a solid span, covers is valid
const cover_type* covers;
};
typedef span* iterator;
typedef const span* const_iterator;
scanline_p8_subpix_avrg_filtering() :
m_last_x(0x7FFFFFF0),
m_covers(),
m_cover_ptr(0),
m_spans(),
m_cur_span(0)
{
}
//--------------------------------------------------------------------
void reset(int min_x, int max_x)
{
unsigned max_len = 3*(max_x - min_x + 3);
if(max_len > m_spans.size())
{
m_spans.resize(max_len);
m_covers.resize(max_len);
}
m_last_x = 0x7FFFFFF0;
m_cover_ptr = &m_covers[0];
m_cur_span = &m_spans[0];
m_cur_span->len = 0;
}
//--------------------------------------------------------------------
void add_cell(int x, unsigned cover1, unsigned cover2, unsigned cover3)
{
// NOTE stippi: My basic idea is that filtering tries to minimize colored
// edges, but it does so by blurring the coverage values. This will also
// affect neighboring pixels and add blur where there were perfectly sharp
// edges. Andrej's method of filtering adds a special case for perfectly
// sharp edges, but the drawback here is that there will be a visible
// transition between blurred and non-blurred subpixels. I had the idea that
// when simply fading the subpixels towards the plain gray-scale-aa values,
// there must be a sweet spot for when colored edges become non-disturbing
// and there is still a benefit of sharpness compared to straight gray-scale-
// aa. The define above enables this method against the colored edges. My
// method still has a drawback, since jaggies in diagonal lines will be more
// visible again than with the filter method.
unsigned char averageWeight = gSubpixelAverageWeight;
unsigned char subpixelWeight = 255 - averageWeight;
unsigned int coverR;
unsigned int coverG;
unsigned int coverB;
unsigned int average = (cover1 + cover2 + cover3 + 2) / 3;
coverR = (cover1 * subpixelWeight + average * averageWeight) >> 8;
coverG = (cover2 * subpixelWeight + average * averageWeight) >> 8;
coverB = (cover3 * subpixelWeight + average * averageWeight) >> 8;
m_cover_ptr[0] = (cover_type)coverR;
m_cover_ptr[1] = (cover_type)coverG;
m_cover_ptr[2] = (cover_type)coverB;
if(x == m_last_x+1 && m_cur_span->len > 0)
{
m_cur_span->len += 3;
}
else
{
m_cur_span++;
m_cur_span->covers = m_cover_ptr;
m_cur_span->x = (int16)x;
m_cur_span->len = 3;
}
m_last_x = x;
m_cover_ptr += 3;
}
//--------------------------------------------------------------------
void add_cells(int x, unsigned len, const cover_type* covers)
{
memcpy(m_cover_ptr, covers, 3 * len * sizeof(cover_type));
if(x == m_last_x+1 && m_cur_span->len > 0)
{
m_cur_span->len += 3 * (int16)len;
}
else
{
m_cur_span++;
m_cur_span->covers = m_cover_ptr;
m_cur_span->x = (int16)x;
m_cur_span->len = 3 * (int16)len;
}
m_cover_ptr += 3 * len;
m_last_x = x + len - 1;
}
//--------------------------------------------------------------------
void add_span(int x, unsigned len, unsigned cover)
{
if(x == m_last_x+1 &&
m_cur_span->len < 0 &&
cover == *m_cur_span->covers)
{
m_cur_span->len -= 3 * (int16)len;
}
else
{
*m_cover_ptr = (cover_type)cover;
m_cur_span++;
m_cur_span->covers = m_cover_ptr;
m_cover_ptr += 3;
m_cur_span->x = (int16)x;
m_cur_span->len = 3 * (int16)(-int(len));
}
m_last_x = x + len - 1;
}
//--------------------------------------------------------------------
void finalize(int y)
{
m_y = y;
}
//--------------------------------------------------------------------
void reset_spans()
{
m_last_x = 0x7FFFFFF0;
m_cover_ptr = &m_covers[0];
m_cur_span = &m_spans[0];
m_cur_span->len = 0;
}
//--------------------------------------------------------------------
int y() const { return m_y; }
unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); }
const_iterator begin() const { return &m_spans[1]; }
private:
scanline_p8_subpix_avrg_filtering(const self_type&);
const self_type& operator = (const self_type&);
int m_last_x;
int m_y;
pod_array<cover_type> m_covers;
cover_type* m_cover_ptr;
pod_array<span> m_spans;
span* m_cur_span;
};
}
#endif
↑ V730 Not all members of a class are initialized inside the constructor. Consider inspecting: m_y.