app_server: add alpha masked mode to DrawBitmapNoScale

* Add another mode to DrawBitmapNoScale for drawing bitmaps using
  B_OP_COPY with alpha masks. It behaves like the definition for
  ClipToPicture from the BeBook: pixels with alpha = 0 are ignored,
  pixels with any alpha > 0 are copied.
  Before, this fell back to the slower generic AGG-pipeline-based
  version.

* Some light refactoring
This commit is contained in:
Julian Harnath
2015-08-23 01:00:09 +02:00
parent f4f05935db
commit 79a483ebbf
2 changed files with 77 additions and 36 deletions
@@ -82,19 +82,22 @@ Painter::BitmapPainter::Draw(const BRect& sourceRect,
if (!_HasScale() && !_HasAffineTransform() && !_HasAlphaMask()) {
if (fColorSpace == B_CMAP8) {
if (fPainter->fDrawingMode == B_OP_COPY) {
DrawBitmapNoScale<CMap8Copy>::Draw(fPainter->fInternal,
fBitmap, 1, fOffset, fDestinationRect);
DrawBitmapNoScale<CMap8Copy> drawNoScale;
drawNoScale.Draw(fPainter->fInternal, fBitmap, 1, fOffset,
fDestinationRect);
return;
}
if (fPainter->fDrawingMode == B_OP_OVER) {
DrawBitmapNoScale<CMap8Over>::Draw(fPainter->fInternal,
fBitmap, 1, fOffset, fDestinationRect);
DrawBitmapNoScale<CMap8Over> drawNoScale;
drawNoScale.Draw(fPainter->fInternal, fBitmap, 1, fOffset,
fDestinationRect);
return;
}
} else if (fColorSpace == B_RGB32) {
if (fPainter->fDrawingMode == B_OP_OVER) {
DrawBitmapNoScale<Bgr32Over>::Draw(fPainter->fInternal,
fBitmap, 4, fOffset, fDestinationRect);
DrawBitmapNoScale<Bgr32Over> drawNoScale;
drawNoScale.Draw(fPainter->fInternal, fBitmap, 4, fOffset,
fDestinationRect);
return;
}
}
@@ -106,16 +109,27 @@ Painter::BitmapPainter::Draw(const BRect& sourceRect,
// optimized version if there is no scale
if (!_HasScale() && !_HasAffineTransform() && !_HasAlphaMask()) {
if (fPainter->fDrawingMode == B_OP_COPY) {
DrawBitmapNoScale<Bgr32Copy>::Draw(fPainter->fInternal,
fBitmap, 4, fOffset, fDestinationRect);
DrawBitmapNoScale<Bgr32Copy> drawNoScale;
drawNoScale.Draw(fPainter->fInternal, fBitmap, 4, fOffset,
fDestinationRect);
return;
}
if (fPainter->fDrawingMode == B_OP_OVER
|| (fPainter->fDrawingMode == B_OP_ALPHA
&& fPainter->fAlphaSrcMode == B_PIXEL_ALPHA
&& fPainter->fAlphaFncMode == B_ALPHA_OVERLAY)) {
DrawBitmapNoScale<Bgr32Alpha>::Draw(fPainter->fInternal,
fBitmap, 4, fOffset, fDestinationRect);
DrawBitmapNoScale<Bgr32Alpha> drawNoScale;
drawNoScale.Draw(fPainter->fInternal, fBitmap, 4, fOffset,
fDestinationRect);
return;
}
}
if (!_HasScale() && !_HasAffineTransform() && _HasAlphaMask()) {
if (fPainter->fDrawingMode == B_OP_COPY) {
DrawBitmapNoScale<Bgr32CopyMasked> drawNoScale;
drawNoScale.Draw(fPainter->fInternal, fBitmap, 4, fOffset,
fDestinationRect);
return;
}
}
@@ -9,12 +9,14 @@
#define DRAW_BITMAP_NO_SCALE_H
#include "IntPoint.h"
#include "IntRect.h"
#include "Painter.h"
template<class BlendType>
struct DrawBitmapNoScale {
static void
public:
void
Draw(PainterAggInterface& aggInterface, agg::rendering_buffer& bitmap,
uint32 bytesPerSourcePixel, IntPoint offset, BRect destinationRect)
{
@@ -49,25 +51,28 @@ struct DrawBitmapNoScale {
}
#endif
const rgb_color* colorMap = SystemPalette();
fColorMap = SystemPalette();
fAlphaMask = aggInterface.fClippedAlphaMask;
renderer_base& baseRenderer = aggInterface.fBaseRenderer;
// copy rects, iterate over clipping boxes
baseRenderer.first_clip_box();
do {
int32 x1 = max_c(baseRenderer.xmin(), left);
int32 x2 = min_c(baseRenderer.xmax(), right);
if (x1 <= x2) {
int32 y1 = max_c(baseRenderer.ymin(), top);
int32 y2 = min_c(baseRenderer.ymax(), bottom);
if (y1 <= y2) {
uint8* dstHandle = dst + y1 * dstBPR + x1 * 4;
const uint8* srcHandle = src + (y1 - offset.y) * srcBPR
+ (x1 - offset.x) * bytesPerSourcePixel;
fRect.left = max_c(baseRenderer.xmin(), left);
fRect.right = min_c(baseRenderer.xmax(), right);
if (fRect.left <= fRect.right) {
fRect.top = max_c(baseRenderer.ymin(), top);
fRect.bottom = min_c(baseRenderer.ymax(), bottom);
if (fRect.top <= fRect.bottom) {
uint8* dstHandle = dst + fRect.top * dstBPR
+ fRect.left * 4;
const uint8* srcHandle = src
+ (fRect.top - offset.y) * srcBPR
+ (fRect.left - offset.x) * bytesPerSourcePixel;
for (; y1 <= y2; y1++) {
BlendType::BlendRow(dstHandle, srcHandle,
x2 - x1 + 1, colorMap);
for (; fRect.top <= fRect.bottom; fRect.top++) {
static_cast<BlendType*>(this)->BlendRow(dstHandle,
srcHandle, fRect.right - fRect.left + 1);
dstHandle += dstBPR;
srcHandle += srcBPR;
@@ -76,18 +81,22 @@ struct DrawBitmapNoScale {
}
} while (baseRenderer.next_clip_box());
}
protected:
IntRect fRect;
const rgb_color* fColorMap;
const agg::clipped_alpha_mask* fAlphaMask;
};
struct CMap8Copy : public DrawBitmapNoScale<CMap8Copy>
{
static void BlendRow(uint8* dst, const uint8* src, int32 numPixels,
const rgb_color* colorMap)
void BlendRow(uint8* dst, const uint8* src, int32 numPixels)
{
uint32* d = (uint32*)dst;
const uint8* s = src;
while (numPixels--) {
const rgb_color c = colorMap[*s++];
const rgb_color c = fColorMap[*s++];
*d++ = (c.alpha << 24) | (c.red << 16) | (c.green << 8) | (c.blue);
}
}
@@ -96,13 +105,12 @@ struct CMap8Copy : public DrawBitmapNoScale<CMap8Copy>
struct CMap8Over : public DrawBitmapNoScale<CMap8Over>
{
static void BlendRow(uint8* dst, const uint8* src, int32 numPixels,
const rgb_color* colorMap)
void BlendRow(uint8* dst, const uint8* src, int32 numPixels)
{
uint32* d = (uint32*)dst;
const uint8* s = src;
while (numPixels--) {
const rgb_color c = colorMap[*s++];
const rgb_color c = fColorMap[*s++];
if (c.alpha)
*d = (c.alpha << 24) | (c.red << 16)
| (c.green << 8) | (c.blue);
@@ -114,8 +122,7 @@ struct CMap8Over : public DrawBitmapNoScale<CMap8Over>
struct Bgr32Copy : public DrawBitmapNoScale<Bgr32Copy>
{
static void BlendRow(uint8* dst, const uint8* src, int32 numPixels,
const rgb_color*)
void BlendRow(uint8* dst, const uint8* src, int32 numPixels)
{
memcpy(dst, src, numPixels * 4);
}
@@ -124,8 +131,7 @@ struct Bgr32Copy : public DrawBitmapNoScale<Bgr32Copy>
struct Bgr32Over : public DrawBitmapNoScale<Bgr32Over>
{
static void BlendRow(uint8* dst, const uint8* src, int32 numPixels,
const rgb_color*)
void BlendRow(uint8* dst, const uint8* src, int32 numPixels)
{
uint32* d = (uint32*)dst;
uint32* s = (uint32*)src;
@@ -141,8 +147,7 @@ struct Bgr32Over : public DrawBitmapNoScale<Bgr32Over>
struct Bgr32Alpha : public DrawBitmapNoScale<Bgr32Alpha>
{
static void BlendRow(uint8* dst, const uint8* src, int32 numPixels,
const rgb_color*)
void BlendRow(uint8* dst, const uint8* src, int32 numPixels)
{
uint32* d = (uint32*)dst;
int32 bytes = numPixels * 4;
@@ -166,4 +171,26 @@ struct Bgr32Alpha : public DrawBitmapNoScale<Bgr32Alpha>
};
struct Bgr32CopyMasked : public DrawBitmapNoScale<Bgr32CopyMasked>
{
void BlendRow(uint8* dst, const uint8* src, int32 numPixels)
{
uint8 covers[numPixels];
fAlphaMask->get_hspan(fRect.left, fRect.top, covers, numPixels);
uint32* destination = (uint32*)dst;
uint32* source = (uint32*)src;
uint8* mask = (uint8*)&covers[0];
while (numPixels--) {
if (*mask != 0)
*destination = *source;
destination++;
source++;
mask++;
}
}
};
#endif // DRAW_BITMAP_NO_SCALE_H