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
26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.graphics.Bitmap.Config;
27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.text.TextUtils;
28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.awt.Color;
30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.awt.Composite;
31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.awt.Graphics2D;
32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.awt.Rectangle;
33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.awt.RenderingHints;
34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.awt.Shape;
35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.awt.geom.AffineTransform;
36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.awt.geom.Arc2D;
37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.awt.image.BufferedImage;
38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/**
41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Delegate implementing the native methods of android.graphics.Canvas
42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Through the layoutlib_create tool, the original native methods of Canvas have been replaced
44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * by calls to methods of the same name in this delegate class.
45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * This class behaves like the original native implementation, but in Java, keeping previously
47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * native data into its own objects and mapping them to int that are sent back and forth between
48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * it and the original Canvas class.
49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @see DelegateManager
51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipublic final class Canvas_Delegate {
54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ---- delegate manager ----
56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private static final DelegateManager<Canvas_Delegate> sManager =
57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            new DelegateManager<Canvas_Delegate>(Canvas_Delegate.class);
58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
59509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ---- delegate helper data ----
61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final static boolean[] sBoolOut = new boolean[1];
63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
64509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ---- delegate data ----
66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private Bitmap_Delegate mBitmap;
67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private GcSnapshot mSnapshot;
68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private DrawFilter_Delegate mDrawFilter = null;
70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
71509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ---- Public Helper methods ----
73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Returns the native delegate associated to a given {@link Canvas} object.
76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public static Canvas_Delegate getDelegate(Canvas canvas) {
785c3d927e17e98e8fd4a9f3c86f7f4def0bcfa816Florin Malita        return sManager.getDelegate(canvas.getNativeCanvasWrapper());
79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Returns the native delegate associated to a given an int referencing a {@link Canvas} object.
83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
8488a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    public static Canvas_Delegate getDelegate(long native_canvas) {
85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return sManager.getDelegate(native_canvas);
86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Returns the current {@link Graphics2D} used to draw.
90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public GcSnapshot getSnapshot() {
92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return mSnapshot;
93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Returns the {@link DrawFilter} delegate or null if none have been set.
97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @return the delegate or null.
99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public DrawFilter_Delegate getDrawFilter() {
101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return mDrawFilter;
102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ---- native methods ----
105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
107509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    /*package*/ static void freeCaches() {
108509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        // nothing to be done here.
109509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    }
110509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
111509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    @LayoutlibDelegate
112509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    /*package*/ static void freeTextLayoutCaches() {
113509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        // nothing to be done here yet.
114509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    }
115509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
116509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    @LayoutlibDelegate
117509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    /*package*/ static long initRaster(long nativeBitmapOrZero) {
118509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        if (nativeBitmapOrZero > 0) {
119509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            // get the Bitmap from the int
120509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(nativeBitmapOrZero);
121509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
122509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            // create a new Canvas_Delegate with the given bitmap and return its new native int.
123509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            Canvas_Delegate newDelegate = new Canvas_Delegate(bitmapDelegate);
124509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
125509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            return sManager.addNewDelegate(newDelegate);
126509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        }
127509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
128509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        // create a new Canvas_Delegate and return its new native int.
129509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        Canvas_Delegate newDelegate = new Canvas_Delegate();
130509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
131509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        return sManager.addNewDelegate(newDelegate);
132509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    }
133509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
134509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    @LayoutlibDelegate
135509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    /*package*/
136509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    static void native_setBitmap(long canvas, long bitmap, boolean copyState) {
137509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        Canvas_Delegate canvasDelegate = sManager.getDelegate(canvas);
138509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
139509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        if (canvasDelegate == null || bitmapDelegate==null) {
140509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            return;
141509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        }
142509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        canvasDelegate.mBitmap = bitmapDelegate;
143509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        canvasDelegate.mSnapshot = GcSnapshot.createDefaultSnapshot(bitmapDelegate);
144509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    }
145509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
146509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    @LayoutlibDelegate
147bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta    /*package*/ static boolean native_isOpaque(long nativeCanvas) {
148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
149bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return canvasDelegate.mBitmap.getConfig() == Config.RGB_565;
155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
158bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta    /*package*/ static int native_getWidth(long nativeCanvas) {
159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
160bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return 0;
163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return canvasDelegate.mBitmap.getImage().getWidth();
166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
169bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta    /*package*/ static int native_getHeight(long nativeCanvas) {
170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
171bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return 0;
174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return canvasDelegate.mBitmap.getImage().getHeight();
177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
180509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    /*package*/ static int native_save(long nativeCanvas, int saveFlags) {
181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
182bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
184509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            return 0;
185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
187509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        return canvasDelegate.save(saveFlags);
188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
191509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    /*package*/ static int native_saveLayer(long nativeCanvas, float l,
192509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                                               float t, float r, float b,
193509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                                               long paint, int layerFlags) {
194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
195bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
197509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            return 0;
198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
200509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(paint);
201509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        if (paintDelegate == null) {
202509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            return 0;
203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
205509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        return canvasDelegate.saveLayer(new RectF(l, t, r, b),
206509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                paintDelegate, layerFlags);
207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
210509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    /*package*/ static int native_saveLayerAlpha(long nativeCanvas, float l,
211509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                                                    float t, float r, float b,
212509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                                                    int alpha, int layerFlags) {
213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
214bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
216509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            return 0;
217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
219509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        return canvasDelegate.saveLayerAlpha(new RectF(l, t, r, b), alpha, layerFlags);
220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
223509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    /*package*/ static void native_restore(long nativeCanvas) {
224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
225bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
227509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            return;
228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
230509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        canvasDelegate.restore();
231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
234509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    /*package*/ static void native_restoreToCount(long nativeCanvas, int saveCount) {
235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
236bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
241509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        canvasDelegate.restoreTo(saveCount);
242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
245bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta    /*package*/ static int native_getSaveCount(long nativeCanvas) {
246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
247bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return 0;
250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return canvasDelegate.getSnapshot().size();
253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
256509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta   /*package*/ static void native_translate(long nativeCanvas, float dx, float dy) {
257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
258bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
263509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        canvasDelegate.getSnapshot().translate(dx, dy);
264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
267509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta       /*package*/ static void native_scale(long nativeCanvas, float sx, float sy) {
268509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            // get the delegate from the native int.
269509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
270509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            if (canvasDelegate == null) {
271509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                return;
272509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            }
273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
274509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            canvasDelegate.getSnapshot().scale(sx, sy);
275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
278509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    /*package*/ static void native_rotate(long nativeCanvas, float degrees) {
279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
280509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
281509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        if (canvasDelegate == null) {
282bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta            return;
283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
284509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
285509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        canvasDelegate.getSnapshot().rotate(Math.toRadians(degrees));
286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
289509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta   /*package*/ static void native_skew(long nativeCanvas, float kx, float ky) {
290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
293509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            return;
294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
296509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        // get the current top graphics2D object.
297509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        GcSnapshot g = canvasDelegate.getSnapshot();
298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
299509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        // get its current matrix
300509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        AffineTransform currentTx = g.getTransform();
301509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        // get the AffineTransform for the given skew.
302509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        float[] mtx = Matrix_Delegate.getSkew(kx, ky);
303509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        AffineTransform matrixTx = Matrix_Delegate.getAffineTransform(mtx);
304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
305509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        // combine them so that the given matrix is applied after.
306509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        currentTx.preConcatenate(matrixTx);
307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
308509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        // give it to the graphics2D as a new matrix replacing all previous transform
309509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        g.setTransform(currentTx);
310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
31388a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_concat(long nCanvas, long nMatrix) {
314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(nMatrix);
321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (matrixDelegate == null) {
322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the current top graphics2D object.
326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        GcSnapshot snapshot = canvasDelegate.getSnapshot();
327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get its current matrix
329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AffineTransform currentTx = snapshot.getTransform();
330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the AffineTransform of the given matrix
331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AffineTransform matrixTx = matrixDelegate.getAffineTransform();
332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // combine them so that the given matrix is applied after.
334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        currentTx.concatenate(matrixTx);
335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // give it to the graphics2D as a new matrix replacing all previous transform
337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        snapshot.setTransform(currentTx);
338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
34188a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_setMatrix(long nCanvas, long nMatrix) {
342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(nMatrix);
349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (matrixDelegate == null) {
350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the current top graphics2D object.
354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        GcSnapshot snapshot = canvasDelegate.getSnapshot();
355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the AffineTransform of the given matrix
357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AffineTransform matrixTx = matrixDelegate.getAffineTransform();
358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // give it to the graphics2D as a new matrix replacing all previous transform
360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        snapshot.setTransform(matrixTx);
361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (matrixDelegate.hasPerspective()) {
363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            assert false;
364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_AFFINE,
365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "android.graphics.Canvas#setMatrix(android.graphics.Matrix) only " +
366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "supports affine transformations.", null, null /*data*/);
367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
37188a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static boolean native_clipRect(long nCanvas,
372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                  float left, float top,
373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                  float right, float bottom,
374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                  int regionOp) {
375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return canvasDelegate.clipRect(left, top, right, bottom, regionOp);
382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
38588a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static boolean native_clipPath(long nativeCanvas,
38688a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath                                                  long nativePath,
387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                  int regionOp) {
388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return true;
391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Path_Delegate pathDelegate = Path_Delegate.getDelegate(nativePath);
394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (pathDelegate == null) {
395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return true;
396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return canvasDelegate.mSnapshot.clip(pathDelegate.getJavaShape(), regionOp);
399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
40288a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static boolean native_clipRegion(long nativeCanvas,
40388a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath                                                    long nativeRegion,
404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                    int regionOp) {
405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return true;
408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Region_Delegate region = Region_Delegate.getDelegate(nativeRegion);
411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (region == null) {
412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return true;
413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return canvasDelegate.mSnapshot.clip(region.getJavaArea(), regionOp);
416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
41988a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void nativeSetDrawFilter(long nativeCanvas, long nativeFilter) {
420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        canvasDelegate.mDrawFilter = DrawFilter_Delegate.getDelegate(nativeFilter);
426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate.mDrawFilter != null &&
428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                canvasDelegate.mDrawFilter.isSupported() == false) {
429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Bridge.getLog().fidelityWarning(LayoutLog.TAG_DRAWFILTER,
430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    canvasDelegate.mDrawFilter.getSupportMessage(), null, null /*data*/);
431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
43588a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static boolean native_getClipBounds(long nativeCanvas,
436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                       Rect bounds) {
437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Rectangle rect = canvasDelegate.getSnapshot().getClip().getBounds();
444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (rect != null && rect.isEmpty() == false) {
445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bounds.left = rect.x;
446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bounds.top = rect.y;
447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bounds.right = rect.x + rect.width;
448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bounds.bottom = rect.y + rect.height;
449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return true;
450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return false;
453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
45688a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_getCTM(long canvas, long matrix) {
457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Canvas_Delegate canvasDelegate = sManager.getDelegate(canvas);
459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(matrix);
464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (matrixDelegate == null) {
465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AffineTransform transform = canvasDelegate.getSnapshot().getTransform();
469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        matrixDelegate.set(Matrix_Delegate.makeValues(transform));
470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
473509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    /*package*/ static boolean native_quickReject(long nativeCanvas, long path) {
474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // FIXME properly implement quickReject
475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return false;
476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
47988a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static boolean native_quickReject(long nativeCanvas,
480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                     float left, float top,
481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                     float right, float bottom) {
482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // FIXME properly implement quickReject
483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return false;
484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
48788a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_drawColor(long nativeCanvas, final int color, final int mode) {
488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        final int w = canvasDelegate.mBitmap.getImage().getWidth();
495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        final int h = canvasDelegate.mBitmap.getImage().getHeight();
496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        draw(nativeCanvas, new GcSnapshot.Drawable() {
497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            @Override
499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            public void draw(Graphics2D graphics, Paint_Delegate paint) {
500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // reset its transform just in case
501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                graphics.setTransform(new AffineTransform());
502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // set the color
504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                graphics.setColor(new Color(color, true /*alpha*/));
505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
5068ee6bcf8096803fe5c4fbc3838a296a692173e49Deepanshu Gupta                Composite composite = PorterDuffUtility.getComposite(
5078ee6bcf8096803fe5c4fbc3838a296a692173e49Deepanshu Gupta                        PorterDuffUtility.getPorterDuffMode(mode), 0xFF);
508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (composite != null) {
509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    graphics.setComposite(composite);
510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                graphics.fillRect(0, 0, w, h);
513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        });
515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
51888a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_drawPaint(long nativeCanvas, long paint) {
519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // FIXME
520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "Canvas.drawPaint is not supported.", null, null /*data*/);
522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
525509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    /*package*/ static void native_drawPoint(long nativeCanvas, float x, float y,
526509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            long nativePaint) {
527509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        // FIXME
528509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
529509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                "Canvas.drawPoint is not supported.", null, null /*data*/);
530509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    }
531509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
532509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    @LayoutlibDelegate
533509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    /*package*/ static void native_drawPoints(long nativeCanvas, float[] pts, int offset, int count,
534509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            long nativePaint) {
535509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        // FIXME
536509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
537509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                "Canvas.drawPoint is not supported.", null, null /*data*/);
538509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    }
539509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
540509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    @LayoutlibDelegate
54188a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_drawLine(long nativeCanvas,
542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            final float startX, final float startY, final float stopX, final float stopY,
54388a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath            long paint) {
544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                new GcSnapshot.Drawable() {
546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    @Override
547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        graphics.drawLine((int)startX, (int)startY, (int)stopX, (int)stopY);
549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        });
551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
554509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    /*package*/ static void native_drawLines(long nativeCanvas,
555509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            final float[] pts, final int offset, final int count,
556509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta            long nativePaint) {
557509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta        draw(nativeCanvas, nativePaint, false /*compositeOnly*/,
558509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                false /*forceSrcMode*/, new GcSnapshot.Drawable() {
559509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                    @Override
560509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                    public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
561509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                        for (int i = 0; i < count; i += 4) {
562509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                            graphics.drawLine((int) pts[i + offset], (int) pts[i + offset + 1],
563509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                                    (int) pts[i + offset + 2], (int) pts[i + offset + 3]);
564509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                        }
565509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                    }
566509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta                });
567509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    }
568509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
569509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta    @LayoutlibDelegate
57088a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_drawRect(long nativeCanvas,
57188a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath            final float left, final float top, final float right, final float bottom, long paint) {
572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                new GcSnapshot.Drawable() {
575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    @Override
576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int style = paintDelegate.getStyle();
578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // draw
580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (style == Paint.Style.FILL.nativeInt ||
581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                style == Paint.Style.FILL_AND_STROKE.nativeInt) {
582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            graphics.fillRect((int)left, (int)top,
583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    (int)(right-left), (int)(bottom-top));
584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (style == Paint.Style.STROKE.nativeInt ||
587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                style == Paint.Style.FILL_AND_STROKE.nativeInt) {
588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            graphics.drawRect((int)left, (int)top,
589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    (int)(right-left), (int)(bottom-top));
590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        });
593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
596bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta    /*package*/ static void native_drawOval(long nativeCanvas, final float left,
597bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta            final float top, final float right, final float bottom, long paint) {
598bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta        if (right > left && bottom > top) {
599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    new GcSnapshot.Drawable() {
601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        @Override
602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            int style = paintDelegate.getStyle();
604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            // draw
606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (style == Paint.Style.FILL.nativeInt ||
607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    style == Paint.Style.FILL_AND_STROKE.nativeInt) {
608bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta                                graphics.fillOval((int)left, (int)top,
609bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta                                        (int)(right - left), (int)(bottom - top));
610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (style == Paint.Style.STROKE.nativeInt ||
613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    style == Paint.Style.FILL_AND_STROKE.nativeInt) {
614bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta                                graphics.drawOval((int)left, (int)top,
615bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta                                        (int)(right - left), (int)(bottom - top));
616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            });
619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
62388a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_drawCircle(long nativeCanvas,
62488a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath            float cx, float cy, float radius, long paint) {
625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        native_drawOval(nativeCanvas,
626bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta                cx - radius, cy - radius, cx + radius, cy + radius,
627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                paint);
628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
63188a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_drawArc(long nativeCanvas,
632bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta            final float left, final float top, final float right, final float bottom,
633bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta            final float startAngle, final float sweep,
63488a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath            final boolean useCenter, long paint) {
635bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta        if (right > left && bottom > top) {
636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    new GcSnapshot.Drawable() {
638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        @Override
639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            int style = paintDelegate.getStyle();
641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            Arc2D.Float arc = new Arc2D.Float(
643bb5d0cc4369590ce892cca2f717f5d5568c5f655Deepanshu Gupta                                    left, top, right - left, bottom - top,
644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    -startAngle, -sweep,
645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    useCenter ? Arc2D.PIE : Arc2D.OPEN);
646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            // draw
648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (style == Paint.Style.FILL.nativeInt ||
649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    style == Paint.Style.FILL_AND_STROKE.nativeInt) {
650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                graphics.fill(arc);
651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (style == Paint.Style.STROKE.nativeInt ||
654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    style == Paint.Style.FILL_AND_STROKE.nativeInt) {
655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                graphics.draw(arc);
656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            });
659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
66388a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_drawRoundRect(long nativeCanvas,
6646376c407d433c91174e4cef735ddb0014461a906Deepanshu Gupta            final float left, final float top, final float right, final float bottom,
6656376c407d433c91174e4cef735ddb0014461a906Deepanshu Gupta            final float rx, final float ry, long paint) {
666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                new GcSnapshot.Drawable() {
668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    @Override
669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int style = paintDelegate.getStyle();
671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // draw
673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (style == Paint.Style.FILL.nativeInt ||
674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                style == Paint.Style.FILL_AND_STROKE.nativeInt) {
675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            graphics.fillRoundRect(
6766376c407d433c91174e4cef735ddb0014461a906Deepanshu Gupta                                    (int)left, (int)top,
6776376c407d433c91174e4cef735ddb0014461a906Deepanshu Gupta                                    (int)(right - left), (int)(bottom - top),
678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    (int)rx, (int)ry);
679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (style == Paint.Style.STROKE.nativeInt ||
682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                style == Paint.Style.FILL_AND_STROKE.nativeInt) {
683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            graphics.drawRoundRect(
6846376c407d433c91174e4cef735ddb0014461a906Deepanshu Gupta                                    (int)left, (int)top,
6856376c407d433c91174e4cef735ddb0014461a906Deepanshu Gupta                                    (int)(right - left), (int)(bottom - top),
686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    (int)rx, (int)ry);
687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        });
690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
693e05bb956ce429618fd4f971a9dc708b9313c59eaDeepanshu Gupta    /*package*/ static void native_drawPath(long nativeCanvas, long path, long paint) {
694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        final Path_Delegate pathDelegate = Path_Delegate.getDelegate(path);
695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (pathDelegate == null) {
696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                new GcSnapshot.Drawable() {
701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    @Override
702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        Shape shape = pathDelegate.getJavaShape();
704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int style = paintDelegate.getStyle();
705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (style == Paint.Style.FILL.nativeInt ||
707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                style == Paint.Style.FILL_AND_STROKE.nativeInt) {
708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            graphics.fill(shape);
709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (style == Paint.Style.STROKE.nativeInt ||
712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                style == Paint.Style.FILL_AND_STROKE.nativeInt) {
713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            graphics.draw(shape);
714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        });
717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
72088a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, long bitmap,
721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 float left, float top,
72288a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath                                                 long nativePaintOrZero,
723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 int canvasDensity,
724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 int screenDensity,
725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 int bitmapDensity) {
726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bitmapDelegate == null) {
729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        BufferedImage image = bitmapDelegate.getImage();
733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float right = left + image.getWidth();
734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        float bottom = top + image.getHeight();
735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero,
737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                0, 0, image.getWidth(), image.getHeight(),
738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                (int)left, (int)top, (int)right, (int)bottom);
739282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
74288a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, long bitmap,
7431840e8f2c73570e7b51c66c03d3a50bd00f3f742Deepanshu Gupta                                 float srcLeft, float srcTop, float srcRight, float srcBottom,
7441840e8f2c73570e7b51c66c03d3a50bd00f3f742Deepanshu Gupta                                 float dstLeft, float dstTop, float dstRight, float dstBottom,
7451840e8f2c73570e7b51c66c03d3a50bd00f3f742Deepanshu Gupta                                 long nativePaintOrZero, int screenDensity, int bitmapDensity) {
746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bitmapDelegate == null) {
749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
7521840e8f2c73570e7b51c66c03d3a50bd00f3f742Deepanshu Gupta        drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero,
7531840e8f2c73570e7b51c66c03d3a50bd00f3f742Deepanshu Gupta                (int)srcLeft, (int)srcTop, (int)srcRight, (int)srcBottom,
7541840e8f2c73570e7b51c66c03d3a50bd00f3f742Deepanshu Gupta                (int)dstLeft, (int)dstTop, (int)dstRight, (int)dstBottom);
755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
75888a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_drawBitmap(long nativeCanvas, int[] colors,
759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                int offset, int stride, final float x,
760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 final float y, int width, int height,
761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 boolean hasAlpha,
76288a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath                                                 long nativePaintOrZero) {
763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // create a temp BufferedImage containing the content.
764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        final BufferedImage image = new BufferedImage(width, height,
765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                hasAlpha ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB);
766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        image.setRGB(0, 0, width, height, colors, offset, stride);
767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        draw(nativeCanvas, nativePaintOrZero, true /*compositeOnly*/, false /*forceSrcMode*/,
769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                new GcSnapshot.Drawable() {
770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    @Override
771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    public void draw(Graphics2D graphics, Paint_Delegate paint) {
772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (paint != null && paint.isFilterBitmap()) {
773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    RenderingHints.VALUE_INTERPOLATION_BILINEAR);
775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        graphics.drawImage(image, (int) x, (int) y, null);
778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        });
780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
78388a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void nativeDrawBitmapMatrix(long nCanvas, long nBitmap,
78488a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath                                                      long nMatrix, long nPaint) {
785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int, which can be null
792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nPaint);
793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(nBitmap);
796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bitmapDelegate == null) {
797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        final BufferedImage image = getImageToDraw(bitmapDelegate, paintDelegate, sBoolOut);
801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(nMatrix);
803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (matrixDelegate == null) {
804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        final AffineTransform mtx = matrixDelegate.getAffineTransform();
808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        canvasDelegate.getSnapshot().draw(new GcSnapshot.Drawable() {
810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                @Override
811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                public void draw(Graphics2D graphics, Paint_Delegate paint) {
812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (paint != null && paint.isFilterBitmap()) {
813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    //FIXME add support for canvas, screen and bitmap densities.
818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    graphics.drawImage(image, mtx, null);
819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }, paintDelegate, true /*compositeOnly*/, false /*forceSrcMode*/);
821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
82488a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void nativeDrawBitmapMesh(long nCanvas, long nBitmap,
825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors,
82688a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath            int colorOffset, long nPaint) {
827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // FIXME
828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "Canvas.drawBitmapMesh is not supported.", null, null /*data*/);
830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
83388a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void nativeDrawVertices(long nCanvas, int mode, int n,
834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float[] verts, int vertOffset,
835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float[] texs, int texOffset,
836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int[] colors, int colorOffset,
837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            short[] indices, int indexOffset,
83888a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath            int indexCount, long nPaint) {
839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // FIXME
840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "Canvas.drawVertices is not supported.", null, null /*data*/);
842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
84584d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta    /*package*/ static void native_drawText(long nativeCanvas, char[] text, int index, int count,
84684d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta            float startX, float startY, int flags, long paint, long typeface) {
84784d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta        drawText(nativeCanvas, text, index, count, startX, startY, flags == Canvas.DIRECTION_RTL,
84884d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                paint, typeface);
849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
85288a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_drawText(long nativeCanvas, String text,
853e05bb956ce429618fd4f971a9dc708b9313c59eaDeepanshu Gupta            int start, int end, float x, float y, final int flags, long paint,
854e05bb956ce429618fd4f971a9dc708b9313c59eaDeepanshu Gupta            long typeface) {
855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int count = end - start;
856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        char[] buffer = TemporaryBuffer.obtain(count);
857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        TextUtils.getChars(text, start, end, buffer, 0);
858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
859e05bb956ce429618fd4f971a9dc708b9313c59eaDeepanshu Gupta        native_drawText(nativeCanvas, buffer, 0, count, x, y, flags, paint, typeface);
860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
86388a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_drawTextRun(long nativeCanvas, String text,
864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int start, int end, int contextStart, int contextEnd,
86584d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta            float x, float y, boolean isRtl, long paint, long typeface) {
866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int count = end - start;
867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        char[] buffer = TemporaryBuffer.obtain(count);
868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        TextUtils.getChars(text, start, end, buffer, 0);
869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
87084d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta        drawText(nativeCanvas, buffer, 0, count, x, y, isRtl, paint, typeface);
871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
87488a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_drawTextRun(long nativeCanvas, char[] text,
875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int start, int count, int contextStart, int contextCount,
87684d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta            float x, float y, boolean isRtl, long paint, long typeface) {
87784d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta        drawText(nativeCanvas, text, start, count, x, y, isRtl, paint, typeface);
878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
88188a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_drawTextOnPath(long nativeCanvas,
882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                     char[] text, int index,
88388a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath                                                     int count, long path,
884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                     float hOffset,
885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                     float vOffset, int bidiFlags,
88684d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                                                     long paint, long typeface) {
887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // FIXME
888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "Canvas.drawTextOnPath is not supported.", null, null /*data*/);
890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
89388a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void native_drawTextOnPath(long nativeCanvas,
89488a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath                                                     String text, long path,
895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                     float hOffset,
896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                     float vOffset,
89784d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                                                     int bidiFlags, long paint,
89884d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                                                     long typeface) {
899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // FIXME
900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "Canvas.drawTextOnPath is not supported.", null, null /*data*/);
902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
90588a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void finalizer(long nativeCanvas) {
906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int so that it can be disposed.
907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        canvasDelegate.dispose();
913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // remove it from the manager.
915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sManager.removeJavaReferenceFor(nativeCanvas);
916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
918509d860907691a8eb7ff4c8b949fbee36db70feaDeepanshu Gupta
919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ---- Private delegate/helper methods ----
920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Executes a {@link GcSnapshot.Drawable} with a given canvas and paint.
923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * <p>Note that the drawable may actually be executed several times if there are
924130d2353edda445b8e36a6b5e4b176fd748035b0Deepanshu Gupta     * layers involved (see {@link #saveLayer(RectF, Paint_Delegate, int)}.
925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
92688a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    private static void draw(long nCanvas, long nPaint, boolean compositeOnly, boolean forceSrcMode,
927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            GcSnapshot.Drawable drawable) {
928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the paint which can be null if nPaint is 0;
935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nPaint);
936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        canvasDelegate.getSnapshot().draw(drawable, paintDelegate, compositeOnly, forceSrcMode);
938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Executes a {@link GcSnapshot.Drawable} with a given canvas. No paint object will be provided
942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * to {@link GcSnapshot.Drawable#draw(Graphics2D, Paint_Delegate)}.
943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * <p>Note that the drawable may actually be executed several times if there are
944130d2353edda445b8e36a6b5e4b176fd748035b0Deepanshu Gupta     * layers involved (see {@link #saveLayer(RectF, Paint_Delegate, int)}.
945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
94688a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    private static void draw(long nCanvas, GcSnapshot.Drawable drawable) {
947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        canvasDelegate.mSnapshot.draw(drawable);
954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
95684d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta    private static void drawText(long nativeCanvas, final char[] text, final int index,
95784d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta            final int count, final float startX, final float startY, final boolean isRtl,
95884d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta            long paint, final long typeface) {
95984d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta
96084d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta        draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
96184d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                new GcSnapshot.Drawable() {
96284d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta            @Override
96384d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta            public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
96484d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                // WARNING: the logic in this method is similar to Paint_Delegate.measureText.
96584d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                // Any change to this method should be reflected in Paint.measureText
96684d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta
96784d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                // assert that the typeface passed is actually the one stored in paint.
96884d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                assert (typeface == paintDelegate.mNativeTypeface);
96984d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta
97084d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                // Paint.TextAlign indicates how the text is positioned relative to X.
97184d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                // LEFT is the default and there's nothing to do.
97284d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                float x = startX;
97384d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                int limit = index + count;
97484d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                if (paintDelegate.getTextAlign() != Paint.Align.LEFT.nativeInt) {
97584d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                    RectF bounds = paintDelegate.measureText(text, index, count, null, 0,
97684d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                            isRtl);
97784d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                    float m = bounds.right - bounds.left;
97884d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                    if (paintDelegate.getTextAlign() == Paint.Align.CENTER.nativeInt) {
97984d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                        x -= m / 2;
98084d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                    } else if (paintDelegate.getTextAlign() == Paint.Align.RIGHT.nativeInt) {
98184d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                        x -= m;
98284d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                    }
98384d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                }
98484d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta
98584d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                new BidiRenderer(graphics, paintDelegate, text).setRenderLocation(x, startY)
98684d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta                        .renderText(index, limit, isRtl, null, 0, true);
98784d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta            }
98884d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta        });
98984d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta    }
99084d1d431cfe3e66029380fa038f8816b06da120aDeepanshu Gupta
991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private Canvas_Delegate(Bitmap_Delegate bitmap) {
992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mSnapshot = GcSnapshot.createDefaultSnapshot(mBitmap = bitmap);
993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private Canvas_Delegate() {
996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mSnapshot = GcSnapshot.createDefaultSnapshot(null /*image*/);
997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
1000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Disposes of the {@link Graphics2D} stack.
1001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
1002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private void dispose() {
1003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mSnapshot.dispose();
1004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private int save(int saveFlags) {
1007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the current save count
1008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int count = mSnapshot.size();
1009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mSnapshot = mSnapshot.save(saveFlags);
1011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // return the old save count
1013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return count;
1014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private int saveLayerAlpha(RectF rect, int alpha, int saveFlags) {
1017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Paint_Delegate paint = new Paint_Delegate();
1018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        paint.setAlpha(alpha);
1019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return saveLayer(rect, paint, saveFlags);
1020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private int saveLayer(RectF rect, Paint_Delegate paint, int saveFlags) {
1023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the current save count
1024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int count = mSnapshot.size();
1025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mSnapshot = mSnapshot.saveLayer(rect, paint, saveFlags);
1027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // return the old save count
1029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return count;
1030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
1033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Restores the {@link GcSnapshot} to <var>saveCount</var>
1034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param saveCount the saveCount
1035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
1036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private void restoreTo(int saveCount) {
1037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mSnapshot = mSnapshot.restoreTo(saveCount);
1038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
1041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Restores the {@link GcSnapshot} to <var>saveCount</var>
1042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param saveCount the saveCount
1043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
1044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private void restore() {
1045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mSnapshot = mSnapshot.restore();
1046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private boolean clipRect(float left, float top, float right, float bottom, int regionOp) {
1049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return mSnapshot.clipRect(left, top, right, bottom, regionOp);
1050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private static void drawBitmap(
105388a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath            long nativeCanvas,
1054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Bitmap_Delegate bitmap,
105588a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath            long nativePaintOrZero,
1056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            final int sleft, final int stop, final int sright, final int sbottom,
1057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            final int dleft, final int dtop, final int dright, final int dbottom) {
1058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
1059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
1060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (canvasDelegate == null) {
1061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
1062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the paint, which could be null if the int is 0
1065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nativePaintOrZero);
1066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        final BufferedImage image = getImageToDraw(bitmap, paintDelegate, sBoolOut);
1068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        draw(nativeCanvas, nativePaintOrZero, true /*compositeOnly*/, sBoolOut[0],
1070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                new GcSnapshot.Drawable() {
1071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    @Override
1072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    public void draw(Graphics2D graphics, Paint_Delegate paint) {
1073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (paint != null && paint.isFilterBitmap()) {
1074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
1075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    RenderingHints.VALUE_INTERPOLATION_BILINEAR);
1076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        //FIXME add support for canvas, screen and bitmap densities.
1079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        graphics.drawImage(image, dleft, dtop, dright, dbottom,
1080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                sleft, stop, sright, sbottom, null);
1081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        });
1083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
1087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Returns a BufferedImage ready for drawing, based on the bitmap and paint delegate.
1088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * The image returns, through a 1-size boolean array, whether the drawing code should
1089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * use a SRC composite no matter what the paint says.
1090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
1091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param bitmap the bitmap
1092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param paint the paint that will be used to draw
1093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param forceSrcMode whether the composite will have to be SRC
1094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @return the image to draw
1095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
1096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private static BufferedImage getImageToDraw(Bitmap_Delegate bitmap, Paint_Delegate paint,
1097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            boolean[] forceSrcMode) {
1098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        BufferedImage image = bitmap.getImage();
1099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        forceSrcMode[0] = false;
1100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // if the bitmap config is alpha_8, then we erase all color value from it
1102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // before drawing it.
1103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bitmap.getConfig() == Bitmap.Config.ALPHA_8) {
1104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fixAlpha8Bitmap(image);
1105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (bitmap.hasAlpha() == false) {
1106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // hasAlpha is merely a rendering hint. There can in fact be alpha values
1107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // in the bitmap but it should be ignored at drawing time.
1108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // There is two ways to do this:
1109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // - override the composite to be SRC. This can only be used if the composite
1110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //   was going to be SRC or SRC_OVER in the first place
1111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // - Create a different bitmap to draw in which all the alpha channel values is set
1112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //   to 0xFF.
1113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (paint != null) {
1114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                Xfermode_Delegate xfermodeDelegate = paint.getXfermode();
1115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (xfermodeDelegate instanceof PorterDuffXfermode_Delegate) {
1116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    PorterDuff.Mode mode =
1117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ((PorterDuffXfermode_Delegate)xfermodeDelegate).getMode();
1118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    forceSrcMode[0] = mode == PorterDuff.Mode.SRC_OVER ||
1120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            mode == PorterDuff.Mode.SRC;
1121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // if we can't force SRC mode, then create a temp bitmap of TYPE_RGB
1125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (forceSrcMode[0] == false) {
1126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                image = Bitmap_Delegate.createCopy(image, BufferedImage.TYPE_INT_RGB, 0xFF);
1127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return image;
1131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private static void fixAlpha8Bitmap(final BufferedImage image) {
1134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int w = image.getWidth();
1135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int h = image.getHeight();
1136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int[] argb = new int[w * h];
1137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        image.getRGB(0, 0, image.getWidth(), image.getHeight(), argb, 0, image.getWidth());
1138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        final int length = argb.length;
1140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (int i = 0 ; i < length; i++) {
1141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            argb[i] &= 0xFF000000;
1142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        image.setRGB(0, 0, w, h, argb, 0, w);
1144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1147