1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Copyright (C) 2010 The Android Open Source Project
3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * you may not use this file except in compliance with the License.
6282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * You may obtain a copy of the License at
7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
9282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Unless required by applicable law or agreed to in writing, software
11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * See the License for the specific language governing permissions and
14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * limitations under the License.
15282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipackage android.graphics;
18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.ide.common.rendering.api.LayoutLog;
20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.layoutlib.bridge.Bridge;
21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.layoutlib.bridge.impl.DelegateManager;
22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.layoutlib.bridge.impl.GcSnapshot;
238ee6bcf8096803fe5c4fbc3838a296a692173e49Deepanshu Guptaimport com.android.layoutlib.bridge.impl.PorterDuffUtility;
24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.tools.layoutlib.annotations.LayoutlibDelegate;
25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
26476e582d2ffdf25102d4c55f8c242baa3d21d37fDeepanshu Guptaimport android.annotation.Nullable;
27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.graphics.Bitmap.Config;
28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.text.TextUtils;
29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.awt.Color;
31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.awt.Composite;
32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.awt.Graphics2D;
33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.awt.Rectangle;
34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.awt.RenderingHints;
35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.awt.Shape;
36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.awt.geom.AffineTransform;
37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.awt.geom.Arc2D;
38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.awt.image.BufferedImage;
39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/**
42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Delegate implementing the native methods of android.graphics.Canvas
43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Through the layoutlib_create tool, the original native methods of Canvas have been replaced
45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * by calls to methods of the same name in this delegate class.
46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * This class behaves like the original native implementation, but in Java, keeping previously
48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * native data into its own objects and mapping them to int that are sent back and forth between
49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * it and the original Canvas class.
50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @see DelegateManager
52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipublic final class Canvas_Delegate {
55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ---- delegate manager ----
57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private static final DelegateManager<Canvas_Delegate> sManager =
58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            new DelegateManager<Canvas_Delegate>(Canvas_Delegate.class);
59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
60509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ---- delegate helper data ----
62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static boolean[] sBoolOut = new boolean[1];
64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
65509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ---- delegate data ----
67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private Bitmap_Delegate mBitmap;
68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private GcSnapshot mSnapshot;
69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private DrawFilter_Delegate mDrawFilter = null;
71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
72509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ---- Public Helper methods ----
74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Returns the native delegate associated to a given {@link Canvas} object.
77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public static Canvas_Delegate getDelegate(Canvas canvas) {
795c3d927e17e98e8fd4a9f3c86f7f4def0bcfa816Florin Malita        return sManager.getDelegate(canvas.getNativeCanvasWrapper());
80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Returns the native delegate associated to a given an int referencing a {@link Canvas} object.
84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
8588a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    public static Canvas_Delegate getDelegate(long native_canvas) {
86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return sManager.getDelegate(native_canvas);
87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Returns the current {@link Graphics2D} used to draw.
91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public GcSnapshot getSnapshot() {
93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return mSnapshot;
94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Returns the {@link DrawFilter} delegate or null if none have been set.
98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @return the delegate or null.
100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public DrawFilter_Delegate getDrawFilter() {
102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return mDrawFilter;
103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ---- native methods ----
106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
108509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    /*package*/ static void freeCaches() {
109509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        // nothing to be done here.
110509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    }
111509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
112509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    @LayoutlibDelegate
113509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    /*package*/ static void freeTextLayoutCaches() {
114509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        // nothing to be done here yet.
115509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    }
116509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
117509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    @LayoutlibDelegate
118d77b9ed7dcc42efca33b225c4594a30aab9e709cDeepanshu Gupta    /*package*/ static long initRaster(@Nullable Bitmap bitmap) {
119d77b9ed7dcc42efca33b225c4594a30aab9e709cDeepanshu Gupta        long nativeBitmapOrZero = 0;
120d77b9ed7dcc42efca33b225c4594a30aab9e709cDeepanshu Gupta        if (bitmap != null) {
121d77b9ed7dcc42efca33b225c4594a30aab9e709cDeepanshu Gupta            nativeBitmapOrZero = bitmap.refSkPixelRef();
122d77b9ed7dcc42efca33b225c4594a30aab9e709cDeepanshu Gupta        }
123509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        if (nativeBitmapOrZero > 0) {
124509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            // get the Bitmap from the int
125509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(nativeBitmapOrZero);
126509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
127509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            // create a new Canvas_Delegate with the given bitmap and return its new native int.
128509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            Canvas_Delegate newDelegate = new Canvas_Delegate(bitmapDelegate);
129509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
130509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            return sManager.addNewDelegate(newDelegate);
131509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        }
132509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
133509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        // create a new Canvas_Delegate and return its new native int.
134509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        Canvas_Delegate newDelegate = new Canvas_Delegate();
135509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
136509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        return sManager.addNewDelegate(newDelegate);
137509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    }
138509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
139509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    @LayoutlibDelegate
140d77b9ed7dcc42efca33b225c4594a30aab9e709cDeepanshu Gupta    /*package*/ static void native_setBitmap(long canvas, Bitmap bitmap) {
141509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        Canvas_Delegate canvasDelegate = sManager.getDelegate(canvas);
142509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
143509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        if (canvasDelegate == null || bitmapDelegate==null) {
144509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            return;
145509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        }
146509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        canvasDelegate.mBitmap = bitmapDelegate;
147509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        canvasDelegate.mSnapshot = GcSnapshot.createDefaultSnapshot(bitmapDelegate);
148509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    }
149509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
150509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    @LayoutlibDelegate
151bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta    /*package*/ static boolean native_isOpaque(long nativeCanvas) {
152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
153bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return canvasDelegate.mBitmap.getConfig() == Config.RGB_565;
159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
162bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta    /*package*/ static int native_getWidth(long nativeCanvas) {
163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
164bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return 0;
167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return canvasDelegate.mBitmap.getImage().getWidth();
170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
173bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta    /*package*/ static int native_getHeight(long nativeCanvas) {
174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
175bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return 0;
178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return canvasDelegate.mBitmap.getImage().getHeight();
181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
184509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    /*package*/ static int native_save(long nativeCanvas, int saveFlags) {
185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
186bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
188509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            return 0;
189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
191509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        return canvasDelegate.save(saveFlags);
192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
195509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    /*package*/ static int native_saveLayer(long nativeCanvas, float l,
196509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                                               float t, float r, float b,
197509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                                               long paint, int layerFlags) {
198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
199bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
201509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            return 0;
202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
204509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(paint);
205509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        if (paintDelegate == null) {
206509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            return 0;
207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
209509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        return canvasDelegate.saveLayer(new RectF(l, t, r, b),
210509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                paintDelegate, layerFlags);
211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
214509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    /*package*/ static int native_saveLayerAlpha(long nativeCanvas, float l,
215509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                                                    float t, float r, float b,
216509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                                                    int alpha, int layerFlags) {
217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
218bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
220509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            return 0;
221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
223509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        return canvasDelegate.saveLayerAlpha(new RectF(l, t, r, b), alpha, layerFlags);
224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
227dbc7ca0bac64e6f0e6f8463ac8e3d43dfac27eaeDeepanshu Gupta    /*package*/ static void native_restore(long nativeCanvas, boolean throwOnUnderflow) {
228dbc7ca0bac64e6f0e6f8463ac8e3d43dfac27eaeDeepanshu Gupta        // FIXME: implement throwOnUnderflow.
229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
230bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
232509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            return;
233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
235509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        canvasDelegate.restore();
236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
239dbc7ca0bac64e6f0e6f8463ac8e3d43dfac27eaeDeepanshu Gupta    /*package*/ static void native_restoreToCount(long nativeCanvas, int saveCount,
240dbc7ca0bac64e6f0e6f8463ac8e3d43dfac27eaeDeepanshu Gupta            boolean throwOnUnderflow) {
241dbc7ca0bac64e6f0e6f8463ac8e3d43dfac27eaeDeepanshu Gupta        // FIXME: implement throwOnUnderflow.
242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
243bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
248509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        canvasDelegate.restoreTo(saveCount);
249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
252bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta    /*package*/ static int native_getSaveCount(long nativeCanvas) {
253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
254bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return 0;
257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return canvasDelegate.getSnapshot().size();
260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
263509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta   /*package*/ static void native_translate(long nativeCanvas, float dx, float dy) {
264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
265bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
270509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        canvasDelegate.getSnapshot().translate(dx, dy);
271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
274509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta       /*package*/ static void native_scale(long nativeCanvas, float sx, float sy) {
275509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            // get the delegate from the native int.
276509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
277509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            if (canvasDelegate == null) {
278509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                return;
279509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            }
280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
281509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            canvasDelegate.getSnapshot().scale(sx, sy);
282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
285509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    /*package*/ static void native_rotate(long nativeCanvas, float degrees) {
286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
287509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
288509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        if (canvasDelegate == null) {
289bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta            return;
290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
291509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
292509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        canvasDelegate.getSnapshot().rotate(Math.toRadians(degrees));
293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
296509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta   /*package*/ static void native_skew(long nativeCanvas, float kx, float ky) {
297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
300509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            return;
301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
303509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        // get the current top graphics2D object.
304509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        GcSnapshot g = canvasDelegate.getSnapshot();
305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
306509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        // get its current matrix
307509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        AffineTransform currentTx = g.getTransform();
308509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        // get the AffineTransform for the given skew.
309509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        float[] mtx = Matrix_Delegate.getSkew(kx, ky);
310509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        AffineTransform matrixTx = Matrix_Delegate.getAffineTransform(mtx);
311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
312509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        // combine them so that the given matrix is applied after.
313509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        currentTx.preConcatenate(matrixTx);
314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
315509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        // give it to the graphics2D as a new matrix replacing all previous transform
316509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        g.setTransform(currentTx);
317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
32088a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_concat(long nCanvas, long nMatrix) {
321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(nMatrix);
328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (matrixDelegate == null) {
329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the current top graphics2D object.
333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        GcSnapshot snapshot = canvasDelegate.getSnapshot();
334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get its current matrix
336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AffineTransform currentTx = snapshot.getTransform();
337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the AffineTransform of the given matrix
338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AffineTransform matrixTx = matrixDelegate.getAffineTransform();
339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // combine them so that the given matrix is applied after.
341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        currentTx.concatenate(matrixTx);
342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // give it to the graphics2D as a new matrix replacing all previous transform
344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        snapshot.setTransform(currentTx);
345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
34888a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_setMatrix(long nCanvas, long nMatrix) {
349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(nMatrix);
356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (matrixDelegate == null) {
357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the current top graphics2D object.
361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        GcSnapshot snapshot = canvasDelegate.getSnapshot();
362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the AffineTransform of the given matrix
364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AffineTransform matrixTx = matrixDelegate.getAffineTransform();
365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // give it to the graphics2D as a new matrix replacing all previous transform
367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        snapshot.setTransform(matrixTx);
368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (matrixDelegate.hasPerspective()) {
370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            assert false;
371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_AFFINE,
372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "android.graphics.Canvas#setMatrix(android.graphics.Matrix) only " +
373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "supports affine transformations.", null, null /*data*/);
374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
37888a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static boolean native_clipRect(long nCanvas,
379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                  float left, float top,
380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                  float right, float bottom,
381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                  int regionOp) {
382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return canvasDelegate.clipRect(left, top, right, bottom, regionOp);
389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
39288a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static boolean native_clipPath(long nativeCanvas,
39388a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath                                                  long nativePath,
394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                  int regionOp) {
395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return true;
398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Path_Delegate pathDelegate = Path_Delegate.getDelegate(nativePath);
401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (pathDelegate == null) {
402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return true;
403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return canvasDelegate.mSnapshot.clip(pathDelegate.getJavaShape(), regionOp);
406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
40988a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static boolean native_clipRegion(long nativeCanvas,
41088a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath                                                    long nativeRegion,
411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                    int regionOp) {
412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return true;
415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Region_Delegate region = Region_Delegate.getDelegate(nativeRegion);
418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (region == null) {
419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return true;
420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return canvasDelegate.mSnapshot.clip(region.getJavaArea(), regionOp);
423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
42688a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void nativeSetDrawFilter(long nativeCanvas, long nativeFilter) {
427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        canvasDelegate.mDrawFilter = DrawFilter_Delegate.getDelegate(nativeFilter);
433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
434d77b9ed7dcc42efca33b225c4594a30aab9e709cDeepanshu Gupta        if (canvasDelegate.mDrawFilter != null && !canvasDelegate.mDrawFilter.isSupported()) {
435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Bridge.getLog().fidelityWarning(LayoutLog.TAG_DRAWFILTER,
436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    canvasDelegate.mDrawFilter.getSupportMessage(), null, null /*data*/);
437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
44188a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static boolean native_getClipBounds(long nativeCanvas,
442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                       Rect bounds) {
443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Rectangle rect = canvasDelegate.getSnapshot().getClip().getBounds();
450d77b9ed7dcc42efca33b225c4594a30aab9e709cDeepanshu Gupta        if (rect != null && !rect.isEmpty()) {
451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bounds.left = rect.x;
452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bounds.top = rect.y;
453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bounds.right = rect.x + rect.width;
454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bounds.bottom = rect.y + rect.height;
455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return true;
456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return false;
459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
46288a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_getCTM(long canvas, long matrix) {
463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Canvas_Delegate canvasDelegate = sManager.getDelegate(canvas);
465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(matrix);
470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (matrixDelegate == null) {
471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AffineTransform transform = canvasDelegate.getSnapshot().getTransform();
475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        matrixDelegate.set(Matrix_Delegate.makeValues(transform));
476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
479509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    /*package*/ static boolean native_quickReject(long nativeCanvas, long path) {
480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // FIXME properly implement quickReject
481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return false;
482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
48588a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static boolean native_quickReject(long nativeCanvas,
486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                     float left, float top,
487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                     float right, float bottom) {
488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // FIXME properly implement quickReject
489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return false;
490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
49388a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_drawColor(long nativeCanvas, final int color, final int mode) {
494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        final int w = canvasDelegate.mBitmap.getImage().getWidth();
501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        final int h = canvasDelegate.mBitmap.getImage().getHeight();
502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        draw(nativeCanvas, new GcSnapshot.Drawable() {
503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void draw(Graphics2D graphics, Paint_Delegate paint) {
506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // reset its transform just in case
507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                graphics.setTransform(new AffineTransform());
508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // set the color
510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                graphics.setColor(new Color(color, true /*alpha*/));
511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
5128ee6bcf8096803fe5c4fbc3838a296a692173e49Deepanshu Gupta                Composite composite = PorterDuffUtility.getComposite(
5138ee6bcf8096803fe5c4fbc3838a296a692173e49Deepanshu Gupta                        PorterDuffUtility.getPorterDuffMode(mode), 0xFF);
514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (composite != null) {
515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    graphics.setComposite(composite);
516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                graphics.fillRect(0, 0, w, h);
519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        });
521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
52488a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_drawPaint(long nativeCanvas, long paint) {
525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // FIXME
526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "Canvas.drawPaint is not supported.", null, null /*data*/);
528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
531509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    /*package*/ static void native_drawPoint(long nativeCanvas, float x, float y,
532509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            long nativePaint) {
533509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        // FIXME
534509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
535509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                "Canvas.drawPoint is not supported.", null, null /*data*/);
536509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    }
537509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
538509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    @LayoutlibDelegate
539509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    /*package*/ static void native_drawPoints(long nativeCanvas, float[] pts, int offset, int count,
540509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            long nativePaint) {
541509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        // FIXME
542509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
543509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                "Canvas.drawPoint is not supported.", null, null /*data*/);
544509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    }
545509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
546509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    @LayoutlibDelegate
54788a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_drawLine(long nativeCanvas,
548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            final float startX, final float startY, final float stopX, final float stopY,
54988a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath            long paint) {
550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                new GcSnapshot.Drawable() {
552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    @Override
553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        graphics.drawLine((int)startX, (int)startY, (int)stopX, (int)stopY);
555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        });
557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
560509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    /*package*/ static void native_drawLines(long nativeCanvas,
561509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            final float[] pts, final int offset, final int count,
562509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            long nativePaint) {
563509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        draw(nativeCanvas, nativePaint, false /*compositeOnly*/,
564509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                false /*forceSrcMode*/, new GcSnapshot.Drawable() {
565509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                    @Override
566509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                    public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
567509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                        for (int i = 0; i < count; i += 4) {
568509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                            graphics.drawLine((int) pts[i + offset], (int) pts[i + offset + 1],
569509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                                    (int) pts[i + offset + 2], (int) pts[i + offset + 3]);
570509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                        }
571509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                    }
572509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                });
573509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    }
574509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
575509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    @LayoutlibDelegate
57688a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_drawRect(long nativeCanvas,
57788a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath            final float left, final float top, final float right, final float bottom, long paint) {
578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                new GcSnapshot.Drawable() {
581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    @Override
582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int style = paintDelegate.getStyle();
584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // draw
586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (style == Paint.Style.FILL.nativeInt ||
587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                style == Paint.Style.FILL_AND_STROKE.nativeInt) {
588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            graphics.fillRect((int)left, (int)top,
589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    (int)(right-left), (int)(bottom-top));
590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (style == Paint.Style.STROKE.nativeInt ||
593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                style == Paint.Style.FILL_AND_STROKE.nativeInt) {
594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            graphics.drawRect((int)left, (int)top,
595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    (int)(right-left), (int)(bottom-top));
596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        });
599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
602bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta    /*package*/ static void native_drawOval(long nativeCanvas, final float left,
603bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta            final float top, final float right, final float bottom, long paint) {
604bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta        if (right > left && bottom > top) {
605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    new GcSnapshot.Drawable() {
607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        @Override
608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            int style = paintDelegate.getStyle();
610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            // draw
612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (style == Paint.Style.FILL.nativeInt ||
613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    style == Paint.Style.FILL_AND_STROKE.nativeInt) {
614bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta                                graphics.fillOval((int)left, (int)top,
615bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta                                        (int)(right - left), (int)(bottom - top));
616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (style == Paint.Style.STROKE.nativeInt ||
619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    style == Paint.Style.FILL_AND_STROKE.nativeInt) {
620bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta                                graphics.drawOval((int)left, (int)top,
621bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta                                        (int)(right - left), (int)(bottom - top));
622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            });
625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
62988a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_drawCircle(long nativeCanvas,
63088a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath            float cx, float cy, float radius, long paint) {
631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        native_drawOval(nativeCanvas,
632bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta                cx - radius, cy - radius, cx + radius, cy + radius,
633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                paint);
634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
63788a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_drawArc(long nativeCanvas,
638bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta            final float left, final float top, final float right, final float bottom,
639bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta            final float startAngle, final float sweep,
64088a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath            final boolean useCenter, long paint) {
641bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta        if (right > left && bottom > top) {
642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    new GcSnapshot.Drawable() {
644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        @Override
645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            int style = paintDelegate.getStyle();
647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            Arc2D.Float arc = new Arc2D.Float(
649bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta                                    left, top, right - left, bottom - top,
650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    -startAngle, -sweep,
651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    useCenter ? Arc2D.PIE : Arc2D.OPEN);
652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            // draw
654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (style == Paint.Style.FILL.nativeInt ||
655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    style == Paint.Style.FILL_AND_STROKE.nativeInt) {
656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                graphics.fill(arc);
657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (style == Paint.Style.STROKE.nativeInt ||
660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    style == Paint.Style.FILL_AND_STROKE.nativeInt) {
661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                graphics.draw(arc);
662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            });
665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
66988a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_drawRoundRect(long nativeCanvas,
6706376c407d433c91174e4cef735ddb0014461a906Deepanshu Gupta            final float left, final float top, final float right, final float bottom,
6716376c407d433c91174e4cef735ddb0014461a906Deepanshu Gupta            final float rx, final float ry, long paint) {
672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                new GcSnapshot.Drawable() {
674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    @Override
675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int style = paintDelegate.getStyle();
677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // draw
679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (style == Paint.Style.FILL.nativeInt ||
680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                style == Paint.Style.FILL_AND_STROKE.nativeInt) {
681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            graphics.fillRoundRect(
6826376c407d433c91174e4cef735ddb0014461a906Deepanshu Gupta                                    (int)left, (int)top,
6836376c407d433c91174e4cef735ddb0014461a906Deepanshu Gupta                                    (int)(right - left), (int)(bottom - top),
6847c834296ac2561d0d630b2ef6b2530344be7afbdDeepanshu Gupta                                    2 * (int)rx, 2 * (int)ry);
685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (style == Paint.Style.STROKE.nativeInt ||
688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                style == Paint.Style.FILL_AND_STROKE.nativeInt) {
689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            graphics.drawRoundRect(
6906376c407d433c91174e4cef735ddb0014461a906Deepanshu Gupta                                    (int)left, (int)top,
6916376c407d433c91174e4cef735ddb0014461a906Deepanshu Gupta                                    (int)(right - left), (int)(bottom - top),
6927c834296ac2561d0d630b2ef6b2530344be7afbdDeepanshu Gupta                                    2 * (int)rx, 2 * (int)ry);
693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        });
696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
699e05bb956ce429618fd4f971a9dc708b9313c59eaDeepanshu Gupta    /*package*/ static void native_drawPath(long nativeCanvas, long path, long paint) {
700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        final Path_Delegate pathDelegate = Path_Delegate.getDelegate(path);
701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (pathDelegate == null) {
702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                new GcSnapshot.Drawable() {
707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    @Override
708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        Shape shape = pathDelegate.getJavaShape();
710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int style = paintDelegate.getStyle();
711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (style == Paint.Style.FILL.nativeInt ||
713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                style == Paint.Style.FILL_AND_STROKE.nativeInt) {
714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            graphics.fill(shape);
715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (style == Paint.Style.STROKE.nativeInt ||
718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                style == Paint.Style.FILL_AND_STROKE.nativeInt) {
719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            graphics.draw(shape);
720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        });
723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
726d77b9ed7dcc42efca33b225c4594a30aab9e709cDeepanshu Gupta    /*package*/ static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, Bitmap bitmap,
727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 float left, float top,
72888a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath                                                 long nativePaintOrZero,
729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 int canvasDensity,
730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 int screenDensity,
731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 int bitmapDensity) {
732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bitmapDelegate == null) {
735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        BufferedImage image = bitmapDelegate.getImage();
739282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float right = left + image.getWidth();
740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float bottom = top + image.getHeight();
741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero,
743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                0, 0, image.getWidth(), image.getHeight(),
744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                (int)left, (int)top, (int)right, (int)bottom);
745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
748d77b9ed7dcc42efca33b225c4594a30aab9e709cDeepanshu Gupta    /*package*/ static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, Bitmap bitmap,
7491840e8f2c73570e7b51c66c03d3a50bd00f3f742Deepanshu Gupta                                 float srcLeft, float srcTop, float srcRight, float srcBottom,
7501840e8f2c73570e7b51c66c03d3a50bd00f3f742Deepanshu Gupta                                 float dstLeft, float dstTop, float dstRight, float dstBottom,
7511840e8f2c73570e7b51c66c03d3a50bd00f3f742Deepanshu Gupta                                 long nativePaintOrZero, int screenDensity, int bitmapDensity) {
752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bitmapDelegate == null) {
755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
7581840e8f2c73570e7b51c66c03d3a50bd00f3f742Deepanshu Gupta        drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero,
7591840e8f2c73570e7b51c66c03d3a50bd00f3f742Deepanshu Gupta                (int)srcLeft, (int)srcTop, (int)srcRight, (int)srcBottom,
7601840e8f2c73570e7b51c66c03d3a50bd00f3f742Deepanshu Gupta                (int)dstLeft, (int)dstTop, (int)dstRight, (int)dstBottom);
761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
76488a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_drawBitmap(long nativeCanvas, int[] colors,
765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                int offset, int stride, final float x,
766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 final float y, int width, int height,
767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 boolean hasAlpha,
76888a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath                                                 long nativePaintOrZero) {
769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // create a temp BufferedImage containing the content.
770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        final BufferedImage image = new BufferedImage(width, height,
771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                hasAlpha ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB);
772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        image.setRGB(0, 0, width, height, colors, offset, stride);
773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        draw(nativeCanvas, nativePaintOrZero, true /*compositeOnly*/, false /*forceSrcMode*/,
775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                new GcSnapshot.Drawable() {
776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    @Override
777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    public void draw(Graphics2D graphics, Paint_Delegate paint) {
778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (paint != null && paint.isFilterBitmap()) {
779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    RenderingHints.VALUE_INTERPOLATION_BILINEAR);
781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        graphics.drawImage(image, (int) x, (int) y, null);
784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        });
786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
789d77b9ed7dcc42efca33b225c4594a30aab9e709cDeepanshu Gupta    /*package*/ static void nativeDrawBitmapMatrix(long nCanvas, Bitmap bitmap,
79088a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath                                                      long nMatrix, long nPaint) {
791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int, which can be null
798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nPaint);
799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
801d77b9ed7dcc42efca33b225c4594a30aab9e709cDeepanshu Gupta        Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bitmapDelegate == null) {
803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        final BufferedImage image = getImageToDraw(bitmapDelegate, paintDelegate, sBoolOut);
807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(nMatrix);
809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (matrixDelegate == null) {
810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        final AffineTransform mtx = matrixDelegate.getAffineTransform();
814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        canvasDelegate.getSnapshot().draw(new GcSnapshot.Drawable() {
816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                @Override
817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                public void draw(Graphics2D graphics, Paint_Delegate paint) {
818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (paint != null && paint.isFilterBitmap()) {
819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    //FIXME add support for canvas, screen and bitmap densities.
824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    graphics.drawImage(image, mtx, null);
825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }, paintDelegate, true /*compositeOnly*/, false /*forceSrcMode*/);
827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
830d77b9ed7dcc42efca33b225c4594a30aab9e709cDeepanshu Gupta    /*package*/ static void nativeDrawBitmapMesh(long nCanvas, Bitmap bitmap,
831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors,
83288a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath            int colorOffset, long nPaint) {
833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // FIXME
834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "Canvas.drawBitmapMesh is not supported.", null, null /*data*/);
836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
83988a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void nativeDrawVertices(long nCanvas, int mode, int n,
840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float[] verts, int vertOffset,
841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float[] texs, int texOffset,
842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int[] colors, int colorOffset,
843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            short[] indices, int indexOffset,
84488a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath            int indexCount, long nPaint) {
845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // FIXME
846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "Canvas.drawVertices is not supported.", null, null /*data*/);
848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
85184d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta    /*package*/ static void native_drawText(long nativeCanvas, char[] text, int index, int count,
85284d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta            float startX, float startY, int flags, long paint, long typeface) {
853c6abf5bff6bbfafa1f133644f02a5d50d5269b7fRaph Levien        drawText(nativeCanvas, text, index, count, startX, startY, (flags & 1) != 0,
85484d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                paint, typeface);
855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
85888a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_drawText(long nativeCanvas, String text,
859e05bb956ce429618fd4f971a9dc708b9313c59eaDeepanshu Gupta            int start, int end, float x, float y, final int flags, long paint,
860e05bb956ce429618fd4f971a9dc708b9313c59eaDeepanshu Gupta            long typeface) {
861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int count = end - start;
862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        char[] buffer = TemporaryBuffer.obtain(count);
863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        TextUtils.getChars(text, start, end, buffer, 0);
864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
865e05bb956ce429618fd4f971a9dc708b9313c59eaDeepanshu Gupta        native_drawText(nativeCanvas, buffer, 0, count, x, y, flags, paint, typeface);
866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
86988a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_drawTextRun(long nativeCanvas, String text,
870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int start, int end, int contextStart, int contextEnd,
87184d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta            float x, float y, boolean isRtl, long paint, long typeface) {
872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int count = end - start;
873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        char[] buffer = TemporaryBuffer.obtain(count);
874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        TextUtils.getChars(text, start, end, buffer, 0);
875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
87684d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta        drawText(nativeCanvas, buffer, 0, count, x, y, isRtl, paint, typeface);
877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
88088a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_drawTextRun(long nativeCanvas, char[] text,
881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int start, int count, int contextStart, int contextCount,
88284d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta            float x, float y, boolean isRtl, long paint, long typeface) {
88384d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta        drawText(nativeCanvas, text, start, count, x, y, isRtl, paint, typeface);
884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
88788a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_drawTextOnPath(long nativeCanvas,
888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                     char[] text, int index,
88988a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath                                                     int count, long path,
890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                     float hOffset,
891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                     float vOffset, int bidiFlags,
89284d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                                                     long paint, long typeface) {
893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // FIXME
894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "Canvas.drawTextOnPath is not supported.", null, null /*data*/);
896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
89988a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_drawTextOnPath(long nativeCanvas,
90088a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath                                                     String text, long path,
901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                     float hOffset,
902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                     float vOffset,
90384d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                                                     int bidiFlags, long paint,
90484d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                                                     long typeface) {
905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // FIXME
906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "Canvas.drawTextOnPath is not supported.", null, null /*data*/);
908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
91188a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void finalizer(long nativeCanvas) {
912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int so that it can be disposed.
913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        canvasDelegate.dispose();
919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // remove it from the manager.
921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sManager.removeJavaReferenceFor(nativeCanvas);
922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
924509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ---- Private delegate/helper methods ----
926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Executes a {@link GcSnapshot.Drawable} with a given canvas and paint.
929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * <p>Note that the drawable may actually be executed several times if there are
930130d2353edda445b8e36a6b5e4b176fd748035b0Deepanshu Gupta     * layers involved (see {@link #saveLayer(RectF, Paint_Delegate, int)}.
931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
93288a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    private static void draw(long nCanvas, long nPaint, boolean compositeOnly, boolean forceSrcMode,
933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            GcSnapshot.Drawable drawable) {
934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the paint which can be null if nPaint is 0;
941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nPaint);
942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        canvasDelegate.getSnapshot().draw(drawable, paintDelegate, compositeOnly, forceSrcMode);
944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Executes a {@link GcSnapshot.Drawable} with a given canvas. No paint object will be provided
948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * to {@link GcSnapshot.Drawable#draw(Graphics2D, Paint_Delegate)}.
949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * <p>Note that the drawable may actually be executed several times if there are
950130d2353edda445b8e36a6b5e4b176fd748035b0Deepanshu Gupta     * layers involved (see {@link #saveLayer(RectF, Paint_Delegate, int)}.
951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
95288a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    private static void draw(long nCanvas, GcSnapshot.Drawable drawable) {
953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        canvasDelegate.mSnapshot.draw(drawable);
960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
96284d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta    private static void drawText(long nativeCanvas, final char[] text, final int index,
96384d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta            final int count, final float startX, final float startY, final boolean isRtl,
96484d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta            long paint, final long typeface) {
96584d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta
96684d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta        draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
96784d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                new GcSnapshot.Drawable() {
96884d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta            @Override
96984d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta            public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
97084d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                // WARNING: the logic in this method is similar to Paint_Delegate.measureText.
97184d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                // Any change to this method should be reflected in Paint.measureText
97284d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta
97384d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                // assert that the typeface passed is actually the one stored in paint.
97484d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                assert (typeface == paintDelegate.mNativeTypeface);
97584d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta
97684d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                // Paint.TextAlign indicates how the text is positioned relative to X.
97784d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                // LEFT is the default and there's nothing to do.
97884d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                float x = startX;
97984d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                int limit = index + count;
98084d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                if (paintDelegate.getTextAlign() != Paint.Align.LEFT.nativeInt) {
98184d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                    RectF bounds = paintDelegate.measureText(text, index, count, null, 0,
98284d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                            isRtl);
98384d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                    float m = bounds.right - bounds.left;
98484d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                    if (paintDelegate.getTextAlign() == Paint.Align.CENTER.nativeInt) {
98584d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                        x -= m / 2;
98684d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                    } else if (paintDelegate.getTextAlign() == Paint.Align.RIGHT.nativeInt) {
98784d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                        x -= m;
98884d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                    }
98984d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                }
99084d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta
99184d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                new BidiRenderer(graphics, paintDelegate, text).setRenderLocation(x, startY)
99284d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                        .renderText(index, limit, isRtl, null, 0, true);
99384d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta            }
99484d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta        });
99584d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta    }
99684d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta
997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private Canvas_Delegate(Bitmap_Delegate bitmap) {
998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mSnapshot = GcSnapshot.createDefaultSnapshot(mBitmap = bitmap);
999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private Canvas_Delegate() {
1002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mSnapshot = GcSnapshot.createDefaultSnapshot(null /*image*/);
1003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
1006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Disposes of the {@link Graphics2D} stack.
1007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
1008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private void dispose() {
1009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mSnapshot.dispose();
1010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private int save(int saveFlags) {
1013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the current save count
1014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int count = mSnapshot.size();
1015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mSnapshot = mSnapshot.save(saveFlags);
1017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // return the old save count
1019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return count;
1020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private int saveLayerAlpha(RectF rect, int alpha, int saveFlags) {
1023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Paint_Delegate paint = new Paint_Delegate();
1024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        paint.setAlpha(alpha);
1025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return saveLayer(rect, paint, saveFlags);
1026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private int saveLayer(RectF rect, Paint_Delegate paint, int saveFlags) {
1029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the current save count
1030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int count = mSnapshot.size();
1031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mSnapshot = mSnapshot.saveLayer(rect, paint, saveFlags);
1033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // return the old save count
1035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return count;
1036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
1039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Restores the {@link GcSnapshot} to <var>saveCount</var>
1040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param saveCount the saveCount
1041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
1042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private void restoreTo(int saveCount) {
1043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mSnapshot = mSnapshot.restoreTo(saveCount);
1044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
1047d77b9ed7dcc42efca33b225c4594a30aab9e709cDeepanshu Gupta     * Restores the top {@link GcSnapshot}
1048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
1049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private void restore() {
1050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mSnapshot = mSnapshot.restore();
1051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private boolean clipRect(float left, float top, float right, float bottom, int regionOp) {
1054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return mSnapshot.clipRect(left, top, right, bottom, regionOp);
1055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private static void drawBitmap(
105888a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath            long nativeCanvas,
1059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Bitmap_Delegate bitmap,
106088a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath            long nativePaintOrZero,
1061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            final int sleft, final int stop, final int sright, final int sbottom,
1062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            final int dleft, final int dtop, final int dright, final int dbottom) {
1063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
1064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
1065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
1066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
1067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the paint, which could be null if the int is 0
1070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nativePaintOrZero);
1071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        final BufferedImage image = getImageToDraw(bitmap, paintDelegate, sBoolOut);
1073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        draw(nativeCanvas, nativePaintOrZero, true /*compositeOnly*/, sBoolOut[0],
1075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                new GcSnapshot.Drawable() {
1076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    @Override
1077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    public void draw(Graphics2D graphics, Paint_Delegate paint) {
1078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (paint != null && paint.isFilterBitmap()) {
1079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
1080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    RenderingHints.VALUE_INTERPOLATION_BILINEAR);
1081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        //FIXME add support for canvas, screen and bitmap densities.
1084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        graphics.drawImage(image, dleft, dtop, dright, dbottom,
1085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                sleft, stop, sright, sbottom, null);
1086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        });
1088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
1092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Returns a BufferedImage ready for drawing, based on the bitmap and paint delegate.
1093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * The image returns, through a 1-size boolean array, whether the drawing code should
1094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * use a SRC composite no matter what the paint says.
1095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
1096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param bitmap the bitmap
1097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param paint the paint that will be used to draw
1098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param forceSrcMode whether the composite will have to be SRC
1099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @return the image to draw
1100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
1101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private static BufferedImage getImageToDraw(Bitmap_Delegate bitmap, Paint_Delegate paint,
1102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            boolean[] forceSrcMode) {
1103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        BufferedImage image = bitmap.getImage();
1104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        forceSrcMode[0] = false;
1105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // if the bitmap config is alpha_8, then we erase all color value from it
1107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // before drawing it.
1108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bitmap.getConfig() == Bitmap.Config.ALPHA_8) {
1109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fixAlpha8Bitmap(image);
1110d77b9ed7dcc42efca33b225c4594a30aab9e709cDeepanshu Gupta        } else if (!bitmap.hasAlpha()) {
1111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // hasAlpha is merely a rendering hint. There can in fact be alpha values
1112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // in the bitmap but it should be ignored at drawing time.
1113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // There is two ways to do this:
1114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // - override the composite to be SRC. This can only be used if the composite
1115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //   was going to be SRC or SRC_OVER in the first place
1116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // - Create a different bitmap to draw in which all the alpha channel values is set
1117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //   to 0xFF.
1118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (paint != null) {
1119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                Xfermode_Delegate xfermodeDelegate = paint.getXfermode();
1120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (xfermodeDelegate instanceof PorterDuffXfermode_Delegate) {
1121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    PorterDuff.Mode mode =
1122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ((PorterDuffXfermode_Delegate)xfermodeDelegate).getMode();
1123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    forceSrcMode[0] = mode == PorterDuff.Mode.SRC_OVER ||
1125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            mode == PorterDuff.Mode.SRC;
1126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // if we can't force SRC mode, then create a temp bitmap of TYPE_RGB
1130d77b9ed7dcc42efca33b225c4594a30aab9e709cDeepanshu Gupta            if (!forceSrcMode[0]) {
1131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                image = Bitmap_Delegate.createCopy(image, BufferedImage.TYPE_INT_RGB, 0xFF);
1132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return image;
1136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private static void fixAlpha8Bitmap(final BufferedImage image) {
1139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int w = image.getWidth();
1140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int h = image.getHeight();
1141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int[] argb = new int[w * h];
1142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        image.getRGB(0, 0, image.getWidth(), image.getHeight(), argb, 0, image.getWidth());
1143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        final int length = argb.length;
1145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (int i = 0 ; i < length; i++) {
1146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            argb[i] &= 0xFF000000;
1147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        image.setRGB(0, 0, w, h, argb, 0, w);
1149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1152