Home | History | Annotate | Download | only in graphics
      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 
     17 package android.graphics;
     18 
     19 import com.android.layoutlib.bridge.impl.DelegateManager;
     20 import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
     21 
     22 import android.graphics.PorterDuff.Mode;
     23 
     24 import java.awt.Graphics2D;
     25 import java.awt.image.BufferedImage;
     26 
     27 import static com.android.layoutlib.bridge.impl.PorterDuffUtility.getComposite;
     28 import static com.android.layoutlib.bridge.impl.PorterDuffUtility.getPorterDuffMode;
     29 
     30 /**
     31  * Delegate implementing the native methods of android.graphics.PorterDuffColorFilter
     32  *
     33  * Through the layoutlib_create tool, the original native methods of PorterDuffColorFilter have
     34  * been replaced by calls to methods of the same name in this delegate class.
     35  *
     36  * This class behaves like the original native implementation, but in Java, keeping previously
     37  * native data into its own objects and mapping them to int that are sent back and forth between
     38  * it and the original PorterDuffColorFilter class.
     39  *
     40  * Because this extends {@link ColorFilter_Delegate}, there's no need to use a
     41  * {@link DelegateManager}, as all the Shader classes will be added to the manager
     42  * owned by {@link ColorFilter_Delegate}.
     43  *
     44  * @see ColorFilter_Delegate
     45  *
     46  */
     47 public class PorterDuffColorFilter_Delegate extends ColorFilter_Delegate {
     48 
     49     // ---- delegate data ----
     50 
     51     private final java.awt.Color mSrcColor;
     52     private final Mode mMode;
     53 
     54 
     55     // ---- Public Helper methods ----
     56 
     57     @Override
     58     public boolean isSupported() {
     59         return true;
     60     }
     61 
     62     @Override
     63     public String getSupportMessage() {
     64         return "PorterDuff Color Filter is not supported for mode: " + mMode.name() + ".";
     65     }
     66 
     67     @Override
     68     public void applyFilter(Graphics2D g, int width, int height) {
     69         g.setComposite(getComposite(mMode, 0xFF));
     70         g.setColor(mSrcColor);
     71         g.fillRect(0, 0, width, height);
     72     }
     73 
     74     // ---- native methods ----
     75 
     76     @LayoutlibDelegate
     77     /*package*/ static long native_CreatePorterDuffFilter(int srcColor, int porterDuffMode) {
     78         PorterDuffColorFilter_Delegate newDelegate =
     79                 new PorterDuffColorFilter_Delegate(srcColor, porterDuffMode);
     80         return sManager.addNewDelegate(newDelegate);
     81     }
     82 
     83 
     84     // ---- Private delegate/helper methods ----
     85 
     86     private PorterDuffColorFilter_Delegate(int srcColor, int mode) {
     87         mSrcColor = new java.awt.Color(srcColor, true /* hasAlpha */);
     88         mMode = getCompatibleMode(getPorterDuffMode(mode));
     89     }
     90 
     91     // For filtering the colors, the src image should contain the "color" only for pixel values
     92     // which are not transparent in the target image. But, we are using a simple rectangular image
     93     // completely filled with color. Hence some Composite rules do not apply as intended. However,
     94     // in such cases, they can usually be mapped to some other mode, which produces an approximately
     95     // equivalent result.
     96     private Mode getCompatibleMode(Mode mode) {
     97         Mode m = mode;
     98         // Modes that are directly supported:
     99         // CLEAR, DST, SRC_IN, DST_IN, DST_OUT, SRC_ATOP, DARKEN, LIGHTEN, MULTIPLY, SCREEN,
    100         // ADD, OVERLAY
    101         switch (mode) {
    102         // Modes that can be mapped to one of the supported modes.
    103         case SRC:
    104             m = Mode.SRC_IN;
    105             break;
    106         case SRC_OVER:
    107             m = Mode.SRC_ATOP;
    108             break;
    109         case DST_OVER:
    110             m = Mode.DST;
    111             break;
    112         case SRC_OUT:
    113             m = Mode.CLEAR;
    114             break;
    115         case DST_ATOP:
    116             m = Mode.DST_IN;
    117             break;
    118         case XOR:
    119             m = Mode.DST_OUT;
    120             break;
    121         }
    122         return m;
    123     }
    124 }
    125