app_server: give Painter direct access to alpha masks

* To use alpha masks in optimized drawing code outside of the AGG
  renderer pipeline, we need to allow access to the alpha mask's
  underlying buffer:

  - AlphaMask gets another method which returns its
    clipped_alpha_mask
  - clipped_alpha_mask gets a get_hspan() method which returns a span
    of alpha values without combining it with anything
  - Painter/PainterAggInterface store a pointer to the
    clipped_alpha_mask (in addition to the AlphaMask's scanline
    container)
This commit is contained in:
Julian Harnath
2015-08-23 01:00:04 +02:00
parent 2a58d5432d
commit f4f05935db
5 changed files with 80 additions and 38 deletions
+7
View File
@@ -220,6 +220,13 @@ AlphaMask::Generate()
}
agg::clipped_alpha_mask*
AlphaMask::Mask()
{
return &fCachedMask;
}
ServerBitmap*
AlphaMask::_RenderPicture() const
{
+1
View File
@@ -32,6 +32,7 @@ public:
void SetPrevious(AlphaMask* mask);
scanline_unpacked_masked_type* Generate();
agg::clipped_alpha_mask* Mask();
private:
ServerBitmap* _RenderPicture() const;
+6 -2
View File
@@ -102,6 +102,7 @@ using std::nothrow;
#define fSubpixRasterizer fInternal.fSubpixRasterizer
#define fSubpixRenderer fInternal.fSubpixRenderer
#define fMaskedUnpackedScanline fInternal.fMaskedUnpackedScanline
#define fClippedAlphaMask fInternal.fClippedAlphaMask
#define fPath fInternal.fPath
#define fCurve fInternal.fCurve
@@ -287,10 +288,13 @@ Painter::SetDrawState(const DrawState* state, int32 xOffset, int32 yOffset)
fSubpixelPrecise = state->SubPixelPrecise();
if (state->GetAlphaMask() != NULL)
if (state->GetAlphaMask() != NULL) {
fMaskedUnpackedScanline = state->GetAlphaMask()->Generate();
else
fClippedAlphaMask = state->GetAlphaMask()->Mask();
} else {
fMaskedUnpackedScanline = NULL;
fClippedAlphaMask = NULL;
}
// any of these conditions means we need to use a different drawing
// mode instance
@@ -29,6 +29,7 @@ struct PainterAggInterface {
fSubpixRasterizer(),
fSubpixRenderer(fBaseRenderer),
fMaskedUnpackedScanline(NULL),
fClippedAlphaMask(NULL),
fPath(),
fCurve(fPath)
{
@@ -58,6 +59,7 @@ struct PainterAggInterface {
// Alpha-Masked mode: for ClipToPicture
// (this uses the standard rasterizer and renderer)
scanline_unpacked_masked_type* fMaskedUnpackedScanline;
agg::clipped_alpha_mask* fClippedAlphaMask;
agg::path_storage fPath;
agg::conv_curve<agg::path_storage> fCurve;
@@ -23,7 +23,7 @@ namespace agg
public:
typedef int8u cover_type;
enum cover_scale_e
{
{
cover_shift = 8,
cover_none = 0,
cover_full = 255
@@ -44,46 +44,13 @@ namespace agg
void combine_hspan(int x, int y, cover_type* dst, int num_pix) const
{
x -= m_xOffset;
y -= m_yOffset;
int xmax = m_rbuf->width() - 1;
int ymax = m_rbuf->height() - 1;
int count = num_pix;
cover_type* covers = dst;
if(y < 0 || y > ymax)
{
memset(dst, m_outside, num_pix * sizeof(cover_type));
bool has_inside = _set_outside(x, y, covers, count);
if (!has_inside)
return;
}
if(x < 0)
{
count += x;
if(count <= 0)
{
memset(dst, m_outside, num_pix * sizeof(cover_type));
return;
}
memset(covers, m_outside, -x * sizeof(cover_type));
covers -= x;
x = 0;
}
if(x + count > xmax)
{
int rest = x + count - xmax - 1;
count -= rest;
if(count <= 0)
{
memset(dst, m_outside, num_pix * sizeof(cover_type));
return;
}
memset(covers + count, m_outside, rest * sizeof(cover_type));
}
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
do
{
@@ -95,6 +62,67 @@ namespace agg
while(--count);
}
void get_hspan(int x, int y, cover_type* dst, int num_pix) const
{
int count = num_pix;
cover_type* covers = dst;
bool has_inside = _set_outside(x, y, covers, count);
if (!has_inside)
return;
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
memcpy(covers, mask, count);
}
private:
bool _set_outside(int& x, int& y, cover_type*& covers,
int& count) const
{
x -= m_xOffset;
y -= m_yOffset;
int xmax = m_rbuf->width() - 1;
int ymax = m_rbuf->height() - 1;
int num_pix = count;
cover_type* dst = covers;
if(y < 0 || y > ymax)
{
memset(dst, m_outside, num_pix * sizeof(cover_type));
return false;
}
if(x < 0)
{
count += x;
if(count <= 0)
{
memset(dst, m_outside, num_pix * sizeof(cover_type));
return false;
}
memset(covers, m_outside, -x * sizeof(cover_type));
covers -= x;
x = 0;
}
if(x + count > xmax)
{
int rest = x + count - xmax - 1;
count -= rest;
if(count <= 0)
{
memset(dst, m_outside, num_pix * sizeof(cover_type));
return false;
}
memset(covers + count, m_outside, rest * sizeof(cover_type));
}
return true;
}
private:
int m_xOffset;
int m_yOffset;