2012-11-30 50 views
3

所以我試圖加快我們正在做的一些繪圖(繪製一部分帶alpha透明度的圓弧),並試圖將整個圓弧緩存到一個單獨的位圖中,並顯示它有選擇地使用alpha蒙版。PorterDuffXfermode DST_IN不按預期工作

從研究,我已經做了(針對Android,this example的Xfermodes API演示和this tool),如果我有例如下面的兩個圖形:

enter image description here

enter image description here

和使用以下繪製:

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); 

我應該得到這個結果:

enter image description here

當目標圖像(圓)被夾到其中源圖像(電弧)的繪製的區域。相反,我得到了整個圈子。如果我只是繪製圓弧,它會出現在正確的位置,如果我使用DST_OUT,則會得到預期結果(圓圈的其他三個象限)的倒數。

我也確保禁用此視圖的硬件渲染,以防Xfermode出現問題,但這並沒有什麼區別。

我打破了它到一個單獨的項目在試圖得到它的工作,並使用下面的代碼最簡單的層面,我還是有同樣的問題:

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); 
    } 
} 

我使用它錯了嗎?我只是想念一些東西?我發現了一個錯誤? :)

回答

4

有一個更便宜和更簡單的方法來實現這一點:使用剪輯。 Canvas.clipRect()就夠了。你的解決方案正在燃燒大量的填充率。您可以通過使用SRC_IN而不是DST_IN來獲得所需的效果。但要小心:它只能在透明位圖或圖層中使用。當您在屏幕上直接繪製時,目標已由窗口背景填充。

+0

謝謝!我沒有意識到onDraw畫布包含窗口背景 - 這使得發生的事情變得更有意義。我使用位圖路徑,因爲沒有簡單的方法將閉合的圓弧繪製爲路徑,然後在clipPath()中使用它。除非你有其他建議,否則我會找到一條自己繪製路徑的路線? – kcoppock

+0

我有一個視圖,我需要刷新每1/25秒。每次創建一個新的透明'Bitmap',然後使用'PotterDuff.Mode',就會花費我大量的FPS和內存,所以這種方法會失敗。我嘗試在屏幕上繪圖(onDraw()提供'Canvas'),但問題是每個PotterDuff.Mode.CLEAR都會使我的Canvas變黑而不是透明(沒有綁定到'Canvas'的'Bitmap') 。所以我明白問題是「目的地已經被窗口背景填充了」?那麼如何用透明背景和PotterDuff.Mode.SRC_IN創建一個快速刷新的視圖?什麼意思是「它會在層中工作」? – cadavre

+0

不要每次創建一個新的位圖,重新使用它。 –