diff --git a/src/servers/app/drawing/AlphaMask.cpp b/src/servers/app/drawing/AlphaMask.cpp index 49636c6296..865425a391 100644 --- a/src/servers/app/drawing/AlphaMask.cpp +++ b/src/servers/app/drawing/AlphaMask.cpp @@ -220,6 +220,13 @@ AlphaMask::Generate() } +agg::clipped_alpha_mask* +AlphaMask::Mask() +{ + return &fCachedMask; +} + + ServerBitmap* AlphaMask::_RenderPicture() const { diff --git a/src/servers/app/drawing/AlphaMask.h b/src/servers/app/drawing/AlphaMask.h index cb1969af7a..81503c0874 100644 --- a/src/servers/app/drawing/AlphaMask.h +++ b/src/servers/app/drawing/AlphaMask.h @@ -32,6 +32,7 @@ public: void SetPrevious(AlphaMask* mask); scanline_unpacked_masked_type* Generate(); + agg::clipped_alpha_mask* Mask(); private: ServerBitmap* _RenderPicture() const; diff --git a/src/servers/app/drawing/Painter/Painter.cpp b/src/servers/app/drawing/Painter/Painter.cpp index 45cd532cc8..c8e83756c2 100644 --- a/src/servers/app/drawing/Painter/Painter.cpp +++ b/src/servers/app/drawing/Painter/Painter.cpp @@ -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 diff --git a/src/servers/app/drawing/Painter/PainterAggInterface.h b/src/servers/app/drawing/Painter/PainterAggInterface.h index 57e9c6fa7e..2f4e6ea16e 100644 --- a/src/servers/app/drawing/Painter/PainterAggInterface.h +++ b/src/servers/app/drawing/Painter/PainterAggInterface.h @@ -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 fCurve; diff --git a/src/servers/app/drawing/Painter/agg_clipped_alpha_mask.h b/src/servers/app/drawing/Painter/agg_clipped_alpha_mask.h index 59c77740e9..08e34a251c 100644 --- a/src/servers/app/drawing/Painter/agg_clipped_alpha_mask.h +++ b/src/servers/app/drawing/Painter/agg_clipped_alpha_mask.h @@ -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;