1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.graphics;
18
19import com.android.ide.common.rendering.api.LayoutLog;
20import com.android.layoutlib.bridge.Bridge;
21import com.android.layoutlib.bridge.impl.DelegateManager;
22import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
23
24import java.awt.AlphaComposite;
25import java.awt.Composite;
26
27/**
28 * Delegate implementing the native methods of android.graphics.PorterDuffXfermode
29 *
30 * Through the layoutlib_create tool, the original native methods of PorterDuffXfermode have been
31 * replaced by calls to methods of the same name in this delegate class.
32 *
33 * This class behaves like the original native implementation, but in Java, keeping previously
34 * native data into its own objects and mapping them to int that are sent back and forth between
35 * it and the original PorterDuffXfermode class.
36 *
37 * Because this extends {@link Xfermode_Delegate}, there's no need to use a
38 * {@link DelegateManager}, as all the PathEffect classes will be added to the manager owned by
39 * {@link Xfermode_Delegate}.
40 *
41 */
42public class PorterDuffXfermode_Delegate extends Xfermode_Delegate {
43
44    // ---- delegate data ----
45
46    private final int mMode;
47
48    // ---- Public Helper methods ----
49
50    public PorterDuff.Mode getMode() {
51        return getPorterDuffMode(mMode);
52    }
53
54    @Override
55    public Composite getComposite(int alpha) {
56        return getComposite(getPorterDuffMode(mMode), alpha);
57    }
58
59    @Override
60    public boolean isSupported() {
61        return true;
62    }
63
64    @Override
65    public String getSupportMessage() {
66        // no message since isSupported returns true;
67        return null;
68    }
69
70    public static PorterDuff.Mode getPorterDuffMode(int mode) {
71        for (PorterDuff.Mode m : PorterDuff.Mode.values()) {
72            if (m.nativeInt == mode) {
73                return m;
74            }
75        }
76
77        Bridge.getLog().error(LayoutLog.TAG_BROKEN,
78                String.format("Unknown PorterDuff.Mode: %d", mode), null /*data*/);
79        assert false;
80        return PorterDuff.Mode.SRC_OVER;
81    }
82
83    public static Composite getComposite(PorterDuff.Mode mode, int alpha) {
84        float falpha = alpha != 0xFF ? (float)alpha / 255.f : 1.f;
85        switch (mode) {
86            case CLEAR:
87                return AlphaComposite.getInstance(AlphaComposite.CLEAR, falpha);
88            case DARKEN:
89                break;
90            case DST:
91                return AlphaComposite.getInstance(AlphaComposite.DST, falpha);
92            case DST_ATOP:
93                return AlphaComposite.getInstance(AlphaComposite.DST_ATOP, falpha);
94            case DST_IN:
95                return AlphaComposite.getInstance(AlphaComposite.DST_IN, falpha);
96            case DST_OUT:
97                return AlphaComposite.getInstance(AlphaComposite.DST_OUT, falpha);
98            case DST_OVER:
99                return AlphaComposite.getInstance(AlphaComposite.DST_OVER, falpha);
100            case LIGHTEN:
101                break;
102            case MULTIPLY:
103                break;
104            case SCREEN:
105                break;
106            case SRC:
107                return AlphaComposite.getInstance(AlphaComposite.SRC, falpha);
108            case SRC_ATOP:
109                return AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, falpha);
110            case SRC_IN:
111                return AlphaComposite.getInstance(AlphaComposite.SRC_IN, falpha);
112            case SRC_OUT:
113                return AlphaComposite.getInstance(AlphaComposite.SRC_OUT, falpha);
114            case SRC_OVER:
115                return AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha);
116            case XOR:
117                return AlphaComposite.getInstance(AlphaComposite.XOR, falpha);
118        }
119
120        Bridge.getLog().fidelityWarning(LayoutLog.TAG_BROKEN,
121                String.format("Unsupported PorterDuff Mode: %s", mode.name()),
122                null, null /*data*/);
123
124        return AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha);
125    }
126
127    // ---- native methods ----
128
129    @LayoutlibDelegate
130    /*package*/ static int nativeCreateXfermode(int mode) {
131        PorterDuffXfermode_Delegate newDelegate = new PorterDuffXfermode_Delegate(mode);
132        return sManager.addNewDelegate(newDelegate);
133    }
134
135    // ---- Private delegate/helper methods ----
136
137    private PorterDuffXfermode_Delegate(int mode) {
138        mMode = mode;
139    }
140}
141