14b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet/*
24b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet * Copyright (C) 2010 The Android Open Source Project
34b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet *
44b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet * Licensed under the Apache License, Version 2.0 (the "License");
54b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet * you may not use this file except in compliance with the License.
64b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet * You may obtain a copy of the License at
74b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet *
84b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet *      http://www.apache.org/licenses/LICENSE-2.0
94b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet *
104b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet * Unless required by applicable law or agreed to in writing, software
114b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet * distributed under the License is distributed on an "AS IS" BASIS,
124b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet * See the License for the specific language governing permissions and
144b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet * limitations under the License.
154b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet */
164b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet
174b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohetpackage android.graphics;
184b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet
19918aaa5717fce6081557c82ce1c439b6922737d5Xavier Ducrohetimport com.android.ide.common.rendering.api.LayoutLog;
20d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohetimport com.android.layoutlib.bridge.Bridge;
21c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport com.android.layoutlib.bridge.impl.DelegateManager;
229a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohetimport com.android.tools.layoutlib.annotations.LayoutlibDelegate;
234b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet
24d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohetimport java.awt.AlphaComposite;
25d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohetimport java.awt.Composite;
26d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
274b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet/**
284b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet * Delegate implementing the native methods of android.graphics.PorterDuffXfermode
294b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet *
304b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet * Through the layoutlib_create tool, the original native methods of PorterDuffXfermode have been
314b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet * replaced by calls to methods of the same name in this delegate class.
324b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet *
334b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet * This class behaves like the original native implementation, but in Java, keeping previously
344b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet * native data into its own objects and mapping them to int that are sent back and forth between
354b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet * it and the original PorterDuffXfermode class.
364b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet *
374b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet * Because this extends {@link Xfermode_Delegate}, there's no need to use a
384b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet * {@link DelegateManager}, as all the PathEffect classes will be added to the manager owned by
394b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet * {@link Xfermode_Delegate}.
404b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet *
414b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet */
424b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohetpublic class PorterDuffXfermode_Delegate extends Xfermode_Delegate {
434b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet
444b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet    // ---- delegate data ----
454b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet
464b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet    private final int mMode;
474b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet
484b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet    // ---- Public Helper methods ----
494b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet
50b1da1afa7418960b650780250bbd34c81af61aa3Xavier Ducrohet    public PorterDuff.Mode getMode() {
51b1da1afa7418960b650780250bbd34c81af61aa3Xavier Ducrohet        return getPorterDuffMode(mMode);
52b1da1afa7418960b650780250bbd34c81af61aa3Xavier Ducrohet    }
53b1da1afa7418960b650780250bbd34c81af61aa3Xavier Ducrohet
54d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    @Override
5563fd87113cea6abec97a6cd966e090e9b590fc3bXavier Ducrohet    public Composite getComposite(int alpha) {
5663fd87113cea6abec97a6cd966e090e9b590fc3bXavier Ducrohet        return getComposite(getPorterDuffMode(mMode), alpha);
57d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
58d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
59d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    @Override
60d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    public boolean isSupported() {
61d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        return true;
62d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
63d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
64d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    @Override
65d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    public String getSupportMessage() {
66d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        // no message since isSupported returns true;
67d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        return null;
68d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
69d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
7063fd87113cea6abec97a6cd966e090e9b590fc3bXavier Ducrohet    public static PorterDuff.Mode getPorterDuffMode(int mode) {
7163fd87113cea6abec97a6cd966e090e9b590fc3bXavier Ducrohet        for (PorterDuff.Mode m : PorterDuff.Mode.values()) {
7263fd87113cea6abec97a6cd966e090e9b590fc3bXavier Ducrohet            if (m.nativeInt == mode) {
7363fd87113cea6abec97a6cd966e090e9b590fc3bXavier Ducrohet                return m;
7463fd87113cea6abec97a6cd966e090e9b590fc3bXavier Ducrohet            }
7563fd87113cea6abec97a6cd966e090e9b590fc3bXavier Ducrohet        }
7663fd87113cea6abec97a6cd966e090e9b590fc3bXavier Ducrohet
77918aaa5717fce6081557c82ce1c439b6922737d5Xavier Ducrohet        Bridge.getLog().error(LayoutLog.TAG_BROKEN,
7851a7e5447de94791c464cda5cc6ebbf616d73c80Xavier Ducrohet                String.format("Unknown PorterDuff.Mode: %d", mode), null /*data*/);
7963fd87113cea6abec97a6cd966e090e9b590fc3bXavier Ducrohet        assert false;
8063fd87113cea6abec97a6cd966e090e9b590fc3bXavier Ducrohet        return PorterDuff.Mode.SRC_OVER;
8163fd87113cea6abec97a6cd966e090e9b590fc3bXavier Ducrohet    }
8263fd87113cea6abec97a6cd966e090e9b590fc3bXavier Ducrohet
8363fd87113cea6abec97a6cd966e090e9b590fc3bXavier Ducrohet    public static Composite getComposite(PorterDuff.Mode mode, int alpha) {
8463fd87113cea6abec97a6cd966e090e9b590fc3bXavier Ducrohet        float falpha = alpha != 0xFF ? (float)alpha / 255.f : 1.f;
8563fd87113cea6abec97a6cd966e090e9b590fc3bXavier Ducrohet        switch (mode) {
86d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            case CLEAR:
8763fd87113cea6abec97a6cd966e090e9b590fc3bXavier Ducrohet                return AlphaComposite.getInstance(AlphaComposite.CLEAR, falpha);
88d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            case DARKEN:
89d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet                break;
90d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            case DST:
9163fd87113cea6abec97a6cd966e090e9b590fc3bXavier Ducrohet                return AlphaComposite.getInstance(AlphaComposite.DST, falpha);
92d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            case DST_ATOP:
9363fd87113cea6abec97a6cd966e090e9b590fc3bXavier Ducrohet                return AlphaComposite.getInstance(AlphaComposite.DST_ATOP, falpha);
94d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            case DST_IN:
9563fd87113cea6abec97a6cd966e090e9b590fc3bXavier Ducrohet                return AlphaComposite.getInstance(AlphaComposite.DST_IN, falpha);
96d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            case DST_OUT:
9763fd87113cea6abec97a6cd966e090e9b590fc3bXavier Ducrohet                return AlphaComposite.getInstance(AlphaComposite.DST_OUT, falpha);
98d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            case DST_OVER:
9963fd87113cea6abec97a6cd966e090e9b590fc3bXavier Ducrohet                return AlphaComposite.getInstance(AlphaComposite.DST_OVER, falpha);
100d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            case LIGHTEN:
101d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet                break;
102d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            case MULTIPLY:
103d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet                break;
104d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            case SCREEN:
105d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet                break;
106d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            case SRC:
10763fd87113cea6abec97a6cd966e090e9b590fc3bXavier Ducrohet                return AlphaComposite.getInstance(AlphaComposite.SRC, falpha);
108d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            case SRC_ATOP:
10963fd87113cea6abec97a6cd966e090e9b590fc3bXavier Ducrohet                return AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, falpha);
110d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            case SRC_IN:
11163fd87113cea6abec97a6cd966e090e9b590fc3bXavier Ducrohet                return AlphaComposite.getInstance(AlphaComposite.SRC_IN, falpha);
112d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            case SRC_OUT:
11363fd87113cea6abec97a6cd966e090e9b590fc3bXavier Ducrohet                return AlphaComposite.getInstance(AlphaComposite.SRC_OUT, falpha);
114d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            case SRC_OVER:
11563fd87113cea6abec97a6cd966e090e9b590fc3bXavier Ducrohet                return AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha);
116d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            case XOR:
11763fd87113cea6abec97a6cd966e090e9b590fc3bXavier Ducrohet                return AlphaComposite.getInstance(AlphaComposite.XOR, falpha);
118d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
119d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
120918aaa5717fce6081557c82ce1c439b6922737d5Xavier Ducrohet        Bridge.getLog().fidelityWarning(LayoutLog.TAG_BROKEN,
12163fd87113cea6abec97a6cd966e090e9b590fc3bXavier Ducrohet                String.format("Unsupported PorterDuff Mode: %s", mode.name()),
12251a7e5447de94791c464cda5cc6ebbf616d73c80Xavier Ducrohet                null, null /*data*/);
123d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
12463fd87113cea6abec97a6cd966e090e9b590fc3bXavier Ducrohet        return AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha);
1254b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet    }
1264b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet
1274b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet    // ---- native methods ----
1284b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet
1299a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
1304b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet    /*package*/ static int nativeCreateXfermode(int mode) {
1314b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet        PorterDuffXfermode_Delegate newDelegate = new PorterDuffXfermode_Delegate(mode);
132cc4977d0fdaf657907912fd6cc2f9426dc8d2e36Xavier Ducrohet        return sManager.addNewDelegate(newDelegate);
1334b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet    }
1344b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet
1354b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet    // ---- Private delegate/helper methods ----
1364b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet
1374b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet    private PorterDuffXfermode_Delegate(int mode) {
1384b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet        mMode = mode;
1394b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet    }
1404b606da91d2d76dd90a427cb3e37ea7df655e8e0Xavier Ducrohet}
141