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* ServerBitmap*
AlphaMask::_RenderPicture() const AlphaMask::_RenderPicture() const
{ {
+1
View File
@@ -32,6 +32,7 @@ public:
void SetPrevious(AlphaMask* mask); void SetPrevious(AlphaMask* mask);
scanline_unpacked_masked_type* Generate(); scanline_unpacked_masked_type* Generate();
agg::clipped_alpha_mask* Mask();
private: private:
ServerBitmap* _RenderPicture() const; ServerBitmap* _RenderPicture() const;
+6 -2
View File
@@ -102,6 +102,7 @@ using std::nothrow;
#define fSubpixRasterizer fInternal.fSubpixRasterizer #define fSubpixRasterizer fInternal.fSubpixRasterizer
#define fSubpixRenderer fInternal.fSubpixRenderer #define fSubpixRenderer fInternal.fSubpixRenderer
#define fMaskedUnpackedScanline fInternal.fMaskedUnpackedScanline #define fMaskedUnpackedScanline fInternal.fMaskedUnpackedScanline
#define fClippedAlphaMask fInternal.fClippedAlphaMask
#define fPath fInternal.fPath #define fPath fInternal.fPath
#define fCurve fInternal.fCurve #define fCurve fInternal.fCurve
@@ -287,10 +288,13 @@ Painter::SetDrawState(const DrawState* state, int32 xOffset, int32 yOffset)
fSubpixelPrecise = state->SubPixelPrecise(); fSubpixelPrecise = state->SubPixelPrecise();
if (state->GetAlphaMask() != NULL) if (state->GetAlphaMask() != NULL) {
fMaskedUnpackedScanline = state->GetAlphaMask()->Generate(); fMaskedUnpackedScanline = state->GetAlphaMask()->Generate();
else fClippedAlphaMask = state->GetAlphaMask()->Mask();
} else {
fMaskedUnpackedScanline = NULL; fMaskedUnpackedScanline = NULL;
fClippedAlphaMask = NULL;
}
// any of these conditions means we need to use a different drawing // any of these conditions means we need to use a different drawing
// mode instance // mode instance
@@ -29,6 +29,7 @@ struct PainterAggInterface {
fSubpixRasterizer(), fSubpixRasterizer(),
fSubpixRenderer(fBaseRenderer), fSubpixRenderer(fBaseRenderer),
fMaskedUnpackedScanline(NULL), fMaskedUnpackedScanline(NULL),
fClippedAlphaMask(NULL),
fPath(), fPath(),
fCurve(fPath) fCurve(fPath)
{ {
@@ -58,6 +59,7 @@ struct PainterAggInterface {
// Alpha-Masked mode: for ClipToPicture // Alpha-Masked mode: for ClipToPicture
// (this uses the standard rasterizer and renderer) // (this uses the standard rasterizer and renderer)
scanline_unpacked_masked_type* fMaskedUnpackedScanline; scanline_unpacked_masked_type* fMaskedUnpackedScanline;
agg::clipped_alpha_mask* fClippedAlphaMask;
agg::path_storage fPath; agg::path_storage fPath;
agg::conv_curve<agg::path_storage> fCurve; agg::conv_curve<agg::path_storage> fCurve;
@@ -43,6 +43,41 @@ namespace agg
} }
void combine_hspan(int x, int y, cover_type* dst, int num_pix) const void combine_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;
do
{
*covers = (cover_type)((cover_full + (*covers) * (*mask))
>> cover_shift);
++covers;
mask += Step;
}
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; x -= m_xOffset;
y -= m_yOffset; y -= m_yOffset;
@@ -50,13 +85,13 @@ namespace agg
int xmax = m_rbuf->width() - 1; int xmax = m_rbuf->width() - 1;
int ymax = m_rbuf->height() - 1; int ymax = m_rbuf->height() - 1;
int count = num_pix; int num_pix = count;
cover_type* covers = dst; cover_type* dst = covers;
if(y < 0 || y > ymax) if(y < 0 || y > ymax)
{ {
memset(dst, m_outside, num_pix * sizeof(cover_type)); memset(dst, m_outside, num_pix * sizeof(cover_type));
return; return false;
} }
if(x < 0) if(x < 0)
@@ -65,7 +100,7 @@ namespace agg
if(count <= 0) if(count <= 0)
{ {
memset(dst, m_outside, num_pix * sizeof(cover_type)); memset(dst, m_outside, num_pix * sizeof(cover_type));
return; return false;
} }
memset(covers, m_outside, -x * sizeof(cover_type)); memset(covers, m_outside, -x * sizeof(cover_type));
covers -= x; covers -= x;
@@ -79,22 +114,15 @@ namespace agg
if(count <= 0) if(count <= 0)
{ {
memset(dst, m_outside, num_pix * sizeof(cover_type)); memset(dst, m_outside, num_pix * sizeof(cover_type));
return; return false;
} }
memset(covers + count, m_outside, rest * sizeof(cover_type)); memset(covers + count, m_outside, rest * sizeof(cover_type));
} }
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; return true;
do
{
*covers = (cover_type)((cover_full + (*covers) * (*mask))
>> cover_shift);
++covers;
mask += Step;
}
while(--count);
} }
private: private:
int m_xOffset; int m_xOffset;
int m_yOffset; int m_yOffset;