PorterDuffXfermode DST_IN无法按预期工作 [英] PorterDuffXfermode DST_IN not working as expected

查看:378
本文介绍了PorterDuffXfermode DST_IN无法按预期工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我试图加快某些绘制速度(绘制具有alpha透明性的弧的一部分),并尝试将整个弧缓存到单独的位图中,并使用alpha蒙版选择性地显示它。

So I'm trying to speed up some drawing we're doing (drawing a portion of an arc with alpha transparency) and was attempting to cache the entire arc into a separate bitmap, and show it selectively with an alpha mask.

根据我所做的研究(用于Android的Xfermodes API演示,此示例此工具),例如,如果我有以下两个图形:

From the research I've done (the Xfermodes API demo for Android, this example, and this tool), if I have for example the following two graphics:

并使用以下图形绘制:

Xfermode DST_IN = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);

canvas.drawBitmap(circle, 0, 0, paint);
paint.setXfermode(DST_IN);
canvas.drawBitmap(arc, 0, 0, paint);
paint.setXfermode(null);

我应该得到以下结果:

目标图片(圆)被裁剪到绘制源图像(圆弧)的区域。相反,我得到了一个完整的圈子。如果仅绘制圆弧,则它会出现在正确的位置,如果使用DST_OUT,则会得到预期结果的倒数(圆的其他三个象限)。

Where the destination image (the circle) is clipped to the area where the source image (the arc) is drawn. Instead, I get the full circle. If I just draw the arc, it appears in the correct location, and if I use DST_OUT instead, I get the inverse of the expected result (the other three quadrants of the circle).

我还确保为该视图禁用硬件渲染,以防Xfermode出现问题,但没有任何区别。

I've also made sure to disable hardware rendering for this view, in case there was an issue with this Xfermode, but it doesn't make a difference.

我在最简单的级别将其分解为一个单独的项目,试图使其正常工作,并使用以下代码,我仍然遇到相同的问题:

I broke it out into a separate project at the simplest level trying to get it to work, and using the following code, I still have the same problem:

public class ClippedView extends View {
    private Xfermode DST_IN, DST_OUT;
    private Paint paint;

    public ClippedView(Context context) {
        super(context);
        init();
    }

    private void init() {
        setLayoutParams(new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        this.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        DST_IN = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
        DST_OUT = new PorterDuffXfermode(PorterDuff.Mode.DST_OUT);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        paint.setColor(Color.GREEN);
        canvas.drawRect(0, 0, getWidth() / 2, getHeight() / 2, paint);
        paint.setColor(Color.BLACK);
        paint.setXfermode(DST_IN);
        canvas.drawCircle(getWidth() / 2, getHeight() / 2, getWidth() / 2, paint);
        paint.setXfermode(null);
    }
}

我使用错了吗?我只是想念什么吗?我找到错误了吗? :)

Am I using it wrong? Am I just missing something? Have I found a bug? :)

推荐答案

有一种更便宜,更轻松的方法来实现:使用裁剪。 Canvas.clipRect()就足够了。您的解决方案消耗了大量的填充率。您可以使用SRC_IN而不是DST_IN获得所需的效果。但是要小心:它只能在透明的位图或图层中使用。当您直接在屏幕上绘制时,目标位置已经被窗口背景填充。

There's a much cheaper and easier way to achieve this: use clipping. Canvas.clipRect() is enough. Your solution is burning a lot of fillrate. You can get the effect you want by using SRC_IN instead of DST_IN. Be careful though: it will work only in a transparent Bitmap or in layer. When you draw directly on screen, the destination is already filled by the window background.

这篇关于PorterDuffXfermode DST_IN无法按预期工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆