blob: 73d274c1d32b07df03c4787843392625edf1e49b [file] [log] [blame]
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.graphics;
18
Xavier Ducrohet918aaa52011-01-13 10:59:34 -080019import com.android.ide.common.rendering.api.LayoutLog;
Xavier Ducrohet168677c2010-12-06 10:11:44 -080020import com.android.layoutlib.bridge.Bridge;
Xavier Ducrohetc2e96512010-11-09 18:25:03 -080021import com.android.layoutlib.bridge.impl.DelegateManager;
Xavier Ducrohetcfdc7842010-12-14 18:05:22 -080022import com.android.layoutlib.bridge.impl.GcSnapshot;
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -080023import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -070024
Xavier Ducrohetb6e53f42011-01-07 18:37:49 -080025import android.graphics.Bitmap.Config;
Xavier Ducrohet5802dea2010-11-01 16:17:18 -070026import android.text.TextUtils;
27
Xavier Ducrohet5802dea2010-11-01 16:17:18 -070028import java.awt.Color;
Xavier Ducrohetd348b6e2010-12-20 08:22:47 -080029import java.awt.Composite;
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -070030import java.awt.Graphics2D;
Xavier Ducrohet5802dea2010-11-01 16:17:18 -070031import java.awt.Rectangle;
32import java.awt.RenderingHints;
Xavier Ducrohetd348b6e2010-12-20 08:22:47 -080033import java.awt.Shape;
Xavier Ducrohet5802dea2010-11-01 16:17:18 -070034import java.awt.geom.AffineTransform;
Xavier Ducrohet9d765812011-03-14 15:12:21 -070035import java.awt.geom.Arc2D;
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -070036import java.awt.image.BufferedImage;
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -070037
Xavier Ducrohet5802dea2010-11-01 16:17:18 -070038
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -070039/**
40 * Delegate implementing the native methods of android.graphics.Canvas
41 *
42 * Through the layoutlib_create tool, the original native methods of Canvas have been replaced
43 * by calls to methods of the same name in this delegate class.
44 *
45 * This class behaves like the original native implementation, but in Java, keeping previously
46 * native data into its own objects and mapping them to int that are sent back and forth between
47 * it and the original Canvas class.
48 *
49 * @see DelegateManager
50 *
51 */
Xavier Ducrohetd348b6e2010-12-20 08:22:47 -080052public final class Canvas_Delegate {
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -070053
54 // ---- delegate manager ----
55 private static final DelegateManager<Canvas_Delegate> sManager =
Xavier Ducrohetf0a53432011-02-23 16:51:08 -080056 new DelegateManager<Canvas_Delegate>(Canvas_Delegate.class);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -070057
58 // ---- delegate helper data ----
59
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -080060 private final static boolean[] sBoolOut = new boolean[1];
61
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -070062 // ---- delegate data ----
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -080063 private Bitmap_Delegate mBitmap;
Xavier Ducrohetd38e7762010-12-21 06:20:28 -080064 private GcSnapshot mSnapshot;
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -070065
Xavier Ducrohetcc4977d2011-02-22 11:54:37 -080066 private DrawFilter_Delegate mDrawFilter = null;
Xavier Ducrohetd43909c2010-12-23 07:16:21 -080067
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -070068 // ---- Public Helper methods ----
69
70 /**
71 * Returns the native delegate associated to a given {@link Canvas} object.
72 */
73 public static Canvas_Delegate getDelegate(Canvas canvas) {
74 return sManager.getDelegate(canvas.mNativeCanvas);
75 }
76
77 /**
78 * Returns the native delegate associated to a given an int referencing a {@link Canvas} object.
79 */
Narayan Kamath84151432014-01-27 14:24:16 +000080 public static Canvas_Delegate getDelegate(long native_canvas) {
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -070081 return sManager.getDelegate(native_canvas);
82 }
83
84 /**
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -070085 * Returns the current {@link Graphics2D} used to draw.
86 */
Xavier Ducrohetd38e7762010-12-21 06:20:28 -080087 public GcSnapshot getSnapshot() {
Xavier Ducrohetcfdc7842010-12-14 18:05:22 -080088 return mSnapshot;
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -070089 }
90
Xavier Ducrohetd43909c2010-12-23 07:16:21 -080091 /**
92 * Returns the {@link DrawFilter} delegate or null if none have been set.
93 *
94 * @return the delegate or null.
95 */
96 public DrawFilter_Delegate getDrawFilter() {
Xavier Ducrohetcc4977d2011-02-22 11:54:37 -080097 return mDrawFilter;
Xavier Ducrohetd43909c2010-12-23 07:16:21 -080098 }
99
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700100 // ---- native methods ----
101
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800102 @LayoutlibDelegate
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700103 /*package*/ static boolean isOpaque(Canvas thisCanvas) {
Xavier Ducrohetb6e53f42011-01-07 18:37:49 -0800104 // get the delegate from the native int.
105 Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
106 if (canvasDelegate == null) {
107 return false;
108 }
109
110 return canvasDelegate.mBitmap.getConfig() == Config.RGB_565;
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700111 }
112
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800113 @LayoutlibDelegate
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700114 /*package*/ static int getWidth(Canvas thisCanvas) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700115 // get the delegate from the native int.
116 Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
117 if (canvasDelegate == null) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700118 return 0;
119 }
120
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800121 return canvasDelegate.mBitmap.getImage().getWidth();
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700122 }
123
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800124 @LayoutlibDelegate
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700125 /*package*/ static int getHeight(Canvas thisCanvas) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700126 // get the delegate from the native int.
127 Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
128 if (canvasDelegate == null) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700129 return 0;
130 }
131
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800132 return canvasDelegate.mBitmap.getImage().getHeight();
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700133 }
134
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800135 @LayoutlibDelegate
136 /*package*/ static void translate(Canvas thisCanvas, float dx, float dy) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700137 // get the delegate from the native int.
138 Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
139 if (canvasDelegate == null) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700140 return;
141 }
142
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800143 canvasDelegate.getSnapshot().translate(dx, dy);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700144 }
145
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800146 @LayoutlibDelegate
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700147 /*package*/ static void rotate(Canvas thisCanvas, float degrees) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700148 // get the delegate from the native int.
149 Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
150 if (canvasDelegate == null) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700151 return;
152 }
153
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800154 canvasDelegate.getSnapshot().rotate(Math.toRadians(degrees));
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700155 }
156
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800157 @LayoutlibDelegate
158 /*package*/ static void scale(Canvas thisCanvas, float sx, float sy) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700159 // get the delegate from the native int.
160 Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
161 if (canvasDelegate == null) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700162 return;
163 }
164
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800165 canvasDelegate.getSnapshot().scale(sx, sy);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700166 }
167
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800168 @LayoutlibDelegate
169 /*package*/ static void skew(Canvas thisCanvas, float kx, float ky) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700170 // get the delegate from the native int.
171 Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
172 if (canvasDelegate == null) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700173 return;
174 }
175
176 // get the current top graphics2D object.
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800177 GcSnapshot g = canvasDelegate.getSnapshot();
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700178
179 // get its current matrix
180 AffineTransform currentTx = g.getTransform();
181 // get the AffineTransform for the given skew.
182 float[] mtx = Matrix_Delegate.getSkew(kx, ky);
183 AffineTransform matrixTx = Matrix_Delegate.getAffineTransform(mtx);
184
185 // combine them so that the given matrix is applied after.
186 currentTx.preConcatenate(matrixTx);
187
188 // give it to the graphics2D as a new matrix replacing all previous transform
189 g.setTransform(currentTx);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700190 }
191
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800192 @LayoutlibDelegate
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700193 /*package*/ static boolean clipRect(Canvas thisCanvas, RectF rect) {
Xavier Ducrohetcfdc7842010-12-14 18:05:22 -0800194 return clipRect(thisCanvas, rect.left, rect.top, rect.right, rect.bottom);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700195 }
196
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800197 @LayoutlibDelegate
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700198 /*package*/ static boolean clipRect(Canvas thisCanvas, Rect rect) {
Xavier Ducrohetcfdc7842010-12-14 18:05:22 -0800199 return clipRect(thisCanvas, (float) rect.left, (float) rect.top,
200 (float) rect.right, (float) rect.bottom);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700201 }
202
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800203 @LayoutlibDelegate
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700204 /*package*/ static boolean clipRect(Canvas thisCanvas, float left, float top, float right,
205 float bottom) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700206 // get the delegate from the native int.
207 Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
208 if (canvasDelegate == null) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700209 return false;
210 }
211
Xavier Ducrohet8da363142010-12-13 16:42:01 -0800212 return canvasDelegate.clipRect(left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700213 }
214
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800215 @LayoutlibDelegate
Xavier Ducrohetcfdc7842010-12-14 18:05:22 -0800216 /*package*/ static boolean clipRect(Canvas thisCanvas, int left, int top, int right,
217 int bottom) {
218
219 return clipRect(thisCanvas, (float) left, (float) top, (float) right, (float) bottom);
220 }
221
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800222 @LayoutlibDelegate
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700223 /*package*/ static int save(Canvas thisCanvas) {
Xavier Ducrohetcfdc7842010-12-14 18:05:22 -0800224 return save(thisCanvas, Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG);
225 }
226
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800227 @LayoutlibDelegate
Xavier Ducrohetcfdc7842010-12-14 18:05:22 -0800228 /*package*/ static int save(Canvas thisCanvas, int saveFlags) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700229 // get the delegate from the native int.
230 Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
231 if (canvasDelegate == null) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700232 return 0;
233 }
234
Xavier Ducrohetcfdc7842010-12-14 18:05:22 -0800235 return canvasDelegate.save(saveFlags);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700236 }
237
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800238 @LayoutlibDelegate
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700239 /*package*/ static void restore(Canvas thisCanvas) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700240 // get the delegate from the native int.
241 Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
242 if (canvasDelegate == null) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700243 return;
244 }
245
Xavier Ducrohetcfdc7842010-12-14 18:05:22 -0800246 canvasDelegate.restore();
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700247 }
248
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800249 @LayoutlibDelegate
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700250 /*package*/ static int getSaveCount(Canvas thisCanvas) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700251 // get the delegate from the native int.
252 Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
253 if (canvasDelegate == null) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700254 return 0;
255 }
256
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800257 return canvasDelegate.getSnapshot().size();
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700258 }
259
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800260 @LayoutlibDelegate
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700261 /*package*/ static void restoreToCount(Canvas thisCanvas, int saveCount) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700262 // get the delegate from the native int.
263 Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
264 if (canvasDelegate == null) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700265 return;
266 }
267
Xavier Ducrohetcfdc7842010-12-14 18:05:22 -0800268 canvasDelegate.restoreTo(saveCount);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700269 }
270
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800271 @LayoutlibDelegate
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700272 /*package*/ static void drawPoints(Canvas thisCanvas, float[] pts, int offset, int count,
273 Paint paint) {
274 // FIXME
Xavier Ducrohet8a80a852011-02-09 19:39:52 -0800275 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
276 "Canvas.drawPoint is not supported.", null, null /*data*/);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700277 }
278
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800279 @LayoutlibDelegate
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700280 /*package*/ static void drawPoint(Canvas thisCanvas, float x, float y, Paint paint) {
281 // FIXME
Xavier Ducrohet8a80a852011-02-09 19:39:52 -0800282 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
283 "Canvas.drawPoint is not supported.", null, null /*data*/);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700284 }
285
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800286 @LayoutlibDelegate
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800287 /*package*/ static void drawLines(Canvas thisCanvas,
288 final float[] pts, final int offset, final int count,
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700289 Paint paint) {
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800290 draw(thisCanvas.mNativeCanvas, paint.mNativePaint, false /*compositeOnly*/,
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800291 false /*forceSrcMode*/, new GcSnapshot.Drawable() {
Xavier Ducrohet46d43cc2012-02-02 15:44:50 -0800292 @Override
Xavier Ducrohet9d765812011-03-14 15:12:21 -0700293 public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800294 for (int i = 0 ; i < count ; i += 4) {
295 graphics.drawLine((int)pts[i + offset], (int)pts[i + offset + 1],
296 (int)pts[i + offset + 2], (int)pts[i + offset + 3]);
297 }
298 }
299 });
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700300 }
301
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800302 @LayoutlibDelegate
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700303 /*package*/ static void freeCaches() {
Xavier Ducrohetb44b43b2010-12-23 10:22:14 -0800304 // nothing to be done here.
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700305 }
306
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800307 @LayoutlibDelegate
Xavier Ducrohetf18c68b2012-05-08 17:14:18 -0700308 /*package*/ static void freeTextLayoutCaches() {
309 // nothing to be done here yet.
310 }
311
312 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000313 /*package*/ static long initRaster(long nativeBitmapOrZero) {
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700314 if (nativeBitmapOrZero > 0) {
315 // get the Bitmap from the int
316 Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(nativeBitmapOrZero);
317
318 // create a new Canvas_Delegate with the given bitmap and return its new native int.
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800319 Canvas_Delegate newDelegate = new Canvas_Delegate(bitmapDelegate);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700320
Xavier Ducrohetcc4977d2011-02-22 11:54:37 -0800321 return sManager.addNewDelegate(newDelegate);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700322 }
Xavier Ducrohet9d765812011-03-14 15:12:21 -0700323
324 // create a new Canvas_Delegate and return its new native int.
325 Canvas_Delegate newDelegate = new Canvas_Delegate();
326
327 return sManager.addNewDelegate(newDelegate);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700328 }
329
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800330 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000331 /*package*/ static void copyNativeCanvasState(long srcCanvas, long dstCanvas) {
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700332 // get the delegate from the native int.
Deepanshu Gupta279c00e2013-05-23 15:20:04 -0700333 Canvas_Delegate srcCanvasDelegate = sManager.getDelegate(srcCanvas);
334 if (srcCanvasDelegate == null) {
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700335 return;
336 }
337
338 // get the delegate from the native int.
Deepanshu Gupta279c00e2013-05-23 15:20:04 -0700339 Canvas_Delegate dstCanvasDelegate = sManager.getDelegate(dstCanvas);
340 if (dstCanvasDelegate == null) {
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700341 return;
342 }
Deepanshu Gupta279c00e2013-05-23 15:20:04 -0700343 // TODO: actually copy the canvas state.
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700344 }
345
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800346 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000347 /*package*/ static long native_saveLayer(long nativeCanvas, RectF bounds,
348 long paint, int layerFlags) {
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800349 // get the delegate from the native int.
350 Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
351 if (canvasDelegate == null) {
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800352 return 0;
353 }
354
355 Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(paint);
356 if (paintDelegate == null) {
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800357 return 0;
358 }
359
360 return canvasDelegate.saveLayer(bounds, paintDelegate, layerFlags);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700361 }
362
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800363 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000364 /*package*/ static long native_saveLayer(long nativeCanvas, float l,
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700365 float t, float r, float b,
Narayan Kamath84151432014-01-27 14:24:16 +0000366 long paint, int layerFlags) {
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800367 // get the delegate from the native int.
368 Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
369 if (canvasDelegate == null) {
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800370 return 0;
371 }
372
373 Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(paint);
374 if (paintDelegate == null) {
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800375 return 0;
376 }
377
378 return canvasDelegate.saveLayer(new RectF(l, t, r, b),
379 paintDelegate, layerFlags);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700380 }
381
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800382 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000383 /*package*/ static long native_saveLayerAlpha(long nativeCanvas,
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700384 RectF bounds, int alpha,
385 int layerFlags) {
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800386 // get the delegate from the native int.
387 Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
388 if (canvasDelegate == null) {
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800389 return 0;
390 }
391
392 return canvasDelegate.saveLayerAlpha(bounds, alpha, layerFlags);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700393 }
394
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800395 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000396 /*package*/ static long native_saveLayerAlpha(long nativeCanvas, float l,
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700397 float t, float r, float b,
398 int alpha, int layerFlags) {
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800399 // get the delegate from the native int.
400 Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
401 if (canvasDelegate == null) {
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800402 return 0;
403 }
404
405 return canvasDelegate.saveLayerAlpha(new RectF(l, t, r, b), alpha, layerFlags);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700406 }
407
408
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800409 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000410 /*package*/ static void native_concat(long nCanvas, long nMatrix) {
Xavier Ducrohet2eea6fa2010-11-24 11:26:40 -0800411 // get the delegate from the native int.
412 Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
413 if (canvasDelegate == null) {
Xavier Ducrohet2eea6fa2010-11-24 11:26:40 -0800414 return;
415 }
416
417 Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(nMatrix);
418 if (matrixDelegate == null) {
Xavier Ducrohet2eea6fa2010-11-24 11:26:40 -0800419 return;
420 }
421
422 // get the current top graphics2D object.
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800423 GcSnapshot snapshot = canvasDelegate.getSnapshot();
Xavier Ducrohet2eea6fa2010-11-24 11:26:40 -0800424
425 // get its current matrix
Xavier Ducrohetcfdc7842010-12-14 18:05:22 -0800426 AffineTransform currentTx = snapshot.getTransform();
Xavier Ducrohet2eea6fa2010-11-24 11:26:40 -0800427 // get the AffineTransform of the given matrix
428 AffineTransform matrixTx = matrixDelegate.getAffineTransform();
429
430 // combine them so that the given matrix is applied after.
Xavier Ducrohetfb93ce92011-06-03 19:38:03 -0700431 currentTx.concatenate(matrixTx);
Xavier Ducrohet2eea6fa2010-11-24 11:26:40 -0800432
433 // give it to the graphics2D as a new matrix replacing all previous transform
Xavier Ducrohetcfdc7842010-12-14 18:05:22 -0800434 snapshot.setTransform(currentTx);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700435 }
436
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800437 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000438 /*package*/ static void native_setMatrix(long nCanvas, long nMatrix) {
Xavier Ducrohet2eea6fa2010-11-24 11:26:40 -0800439 // get the delegate from the native int.
440 Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
441 if (canvasDelegate == null) {
Xavier Ducrohetd43909c2010-12-23 07:16:21 -0800442 return;
Xavier Ducrohet2eea6fa2010-11-24 11:26:40 -0800443 }
444
445 Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(nMatrix);
446 if (matrixDelegate == null) {
Xavier Ducrohetd43909c2010-12-23 07:16:21 -0800447 return;
Xavier Ducrohet2eea6fa2010-11-24 11:26:40 -0800448 }
449
450 // get the current top graphics2D object.
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800451 GcSnapshot snapshot = canvasDelegate.getSnapshot();
Xavier Ducrohet2eea6fa2010-11-24 11:26:40 -0800452
453 // get the AffineTransform of the given matrix
454 AffineTransform matrixTx = matrixDelegate.getAffineTransform();
455
456 // give it to the graphics2D as a new matrix replacing all previous transform
Xavier Ducrohetcfdc7842010-12-14 18:05:22 -0800457 snapshot.setTransform(matrixTx);
Xavier Ducrohet2eea6fa2010-11-24 11:26:40 -0800458
Xavier Ducrohet168677c2010-12-06 10:11:44 -0800459 if (matrixDelegate.hasPerspective()) {
Xavier Ducrohetcfdc7842010-12-14 18:05:22 -0800460 assert false;
Xavier Ducrohet918aaa52011-01-13 10:59:34 -0800461 Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_AFFINE,
Xavier Ducrohet168677c2010-12-06 10:11:44 -0800462 "android.graphics.Canvas#setMatrix(android.graphics.Matrix) only " +
Xavier Ducrohet51a7e542011-01-14 16:40:43 -0800463 "supports affine transformations.", null, null /*data*/);
Xavier Ducrohet168677c2010-12-06 10:11:44 -0800464 }
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700465 }
466
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800467 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000468 /*package*/ static boolean native_clipRect(long nCanvas,
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700469 float left, float top,
470 float right, float bottom,
471 int regionOp) {
Xavier Ducrohet8da363142010-12-13 16:42:01 -0800472
473 // get the delegate from the native int.
474 Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
475 if (canvasDelegate == null) {
Xavier Ducrohetd43909c2010-12-23 07:16:21 -0800476 return false;
Xavier Ducrohet8da363142010-12-13 16:42:01 -0800477 }
478
Xavier Ducrohetcfdc7842010-12-14 18:05:22 -0800479 return canvasDelegate.clipRect(left, top, right, bottom, regionOp);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700480 }
481
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800482 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000483 /*package*/ static boolean native_clipPath(long nativeCanvas,
484 long nativePath,
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700485 int regionOp) {
Xavier Ducrohetb44b43b2010-12-23 10:22:14 -0800486 Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
487 if (canvasDelegate == null) {
488 return true;
489 }
490
491 Path_Delegate pathDelegate = Path_Delegate.getDelegate(nativePath);
492 if (pathDelegate == null) {
493 return true;
494 }
495
496 return canvasDelegate.mSnapshot.clip(pathDelegate.getJavaShape(), regionOp);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700497 }
498
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800499 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000500 /*package*/ static boolean native_clipRegion(long nativeCanvas,
501 long nativeRegion,
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700502 int regionOp) {
Xavier Ducrohetb44b43b2010-12-23 10:22:14 -0800503 Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
504 if (canvasDelegate == null) {
505 return true;
506 }
507
508 Region_Delegate region = Region_Delegate.getDelegate(nativeRegion);
509 if (region == null) {
510 return true;
511 }
512
513 return canvasDelegate.mSnapshot.clip(region.getJavaArea(), regionOp);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700514 }
515
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800516 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000517 /*package*/ static void nativeSetDrawFilter(long nativeCanvas, long nativeFilter) {
Xavier Ducrohetd43909c2010-12-23 07:16:21 -0800518 Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
519 if (canvasDelegate == null) {
520 return;
521 }
522
Xavier Ducrohetcc4977d2011-02-22 11:54:37 -0800523 canvasDelegate.mDrawFilter = DrawFilter_Delegate.getDelegate(nativeFilter);
Xavier Ducrohetd43909c2010-12-23 07:16:21 -0800524
Xavier Ducrohetcc4977d2011-02-22 11:54:37 -0800525 if (canvasDelegate.mDrawFilter != null &&
526 canvasDelegate.mDrawFilter.isSupported() == false) {
Xavier Ducrohet918aaa52011-01-13 10:59:34 -0800527 Bridge.getLog().fidelityWarning(LayoutLog.TAG_DRAWFILTER,
Xavier Ducrohetcc4977d2011-02-22 11:54:37 -0800528 canvasDelegate.mDrawFilter.getSupportMessage(), null, null /*data*/);
Xavier Ducrohetd43909c2010-12-23 07:16:21 -0800529 }
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700530 }
531
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800532 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000533 /*package*/ static boolean native_getClipBounds(long nativeCanvas,
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700534 Rect bounds) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700535 // get the delegate from the native int.
536 Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
537 if (canvasDelegate == null) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700538 return false;
539 }
540
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800541 Rectangle rect = canvasDelegate.getSnapshot().getClip().getBounds();
Xavier Ducroheta7cac5e02011-01-06 15:50:42 -0800542 if (rect != null && rect.isEmpty() == false) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700543 bounds.left = rect.x;
544 bounds.top = rect.y;
545 bounds.right = rect.x + rect.width;
546 bounds.bottom = rect.y + rect.height;
547 return true;
548 }
Xavier Ducroheta7cac5e02011-01-06 15:50:42 -0800549
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700550 return false;
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700551 }
552
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800553 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000554 /*package*/ static void native_getCTM(long canvas, long matrix) {
Xavier Ducrohetb6e53f42011-01-07 18:37:49 -0800555 // get the delegate from the native int.
556 Canvas_Delegate canvasDelegate = sManager.getDelegate(canvas);
557 if (canvasDelegate == null) {
558 return;
559 }
560
561 Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(matrix);
562 if (matrixDelegate == null) {
563 return;
564 }
565
566 AffineTransform transform = canvasDelegate.getSnapshot().getTransform();
567 matrixDelegate.set(Matrix_Delegate.makeValues(transform));
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700568 }
569
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800570 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000571 /*package*/ static boolean native_quickReject(long nativeCanvas,
Deepanshu Gupta279c00e2013-05-23 15:20:04 -0700572 RectF rect) {
Xavier Ducrohet251d2e92010-11-01 22:02:08 -0700573 // FIXME properly implement quickReject
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700574 return false;
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700575 }
576
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800577 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000578 /*package*/ static boolean native_quickReject(long nativeCanvas,
579 long path) {
Xavier Ducrohet251d2e92010-11-01 22:02:08 -0700580 // FIXME properly implement quickReject
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700581 return false;
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700582 }
583
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800584 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000585 /*package*/ static boolean native_quickReject(long nativeCanvas,
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700586 float left, float top,
Deepanshu Gupta279c00e2013-05-23 15:20:04 -0700587 float right, float bottom) {
Xavier Ducrohet251d2e92010-11-01 22:02:08 -0700588 // FIXME properly implement quickReject
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700589 return false;
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700590 }
591
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800592 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000593 /*package*/ static void native_drawRGB(long nativeCanvas, int r, int g, int b) {
Xavier Ducrohet251d2e92010-11-01 22:02:08 -0700594 native_drawColor(nativeCanvas, 0xFF000000 | r << 16 | (g&0xFF) << 8 | (b&0xFF),
595 PorterDuff.Mode.SRC_OVER.nativeInt);
596
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700597 }
598
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800599 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000600 /*package*/ static void native_drawARGB(long nativeCanvas, int a, int r, int g, int b) {
Xavier Ducrohet251d2e92010-11-01 22:02:08 -0700601 native_drawColor(nativeCanvas, a << 24 | (r&0xFF) << 16 | (g&0xFF) << 8 | (b&0xFF),
602 PorterDuff.Mode.SRC_OVER.nativeInt);
603 }
604
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800605 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000606 /*package*/ static void native_drawColor(long nativeCanvas, int color) {
Xavier Ducrohet251d2e92010-11-01 22:02:08 -0700607 native_drawColor(nativeCanvas, color, PorterDuff.Mode.SRC_OVER.nativeInt);
608 }
609
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800610 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000611 /*package*/ static void native_drawColor(long nativeCanvas, final int color, final int mode) {
Xavier Ducrohetabff6532010-11-01 18:45:20 -0700612 // get the delegate from the native int.
613 Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
614 if (canvasDelegate == null) {
Xavier Ducrohetabff6532010-11-01 18:45:20 -0700615 return;
616 }
617
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800618 final int w = canvasDelegate.mBitmap.getImage().getWidth();
619 final int h = canvasDelegate.mBitmap.getImage().getHeight();
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800620 draw(nativeCanvas, new GcSnapshot.Drawable() {
Xavier Ducrohetabff6532010-11-01 18:45:20 -0700621
Xavier Ducrohet46d43cc2012-02-02 15:44:50 -0800622 @Override
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800623 public void draw(Graphics2D graphics, Paint_Delegate paint) {
624 // reset its transform just in case
625 graphics.setTransform(new AffineTransform());
Xavier Ducrohet251d2e92010-11-01 22:02:08 -0700626
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800627 // set the color
628 graphics.setColor(new Color(color, true /*alpha*/));
629
630 Composite composite = PorterDuffXfermode_Delegate.getComposite(
631 PorterDuffXfermode_Delegate.getPorterDuffMode(mode), 0xFF);
632 if (composite != null) {
633 graphics.setComposite(composite);
634 }
635
636 graphics.fillRect(0, 0, w, h);
Xavier Ducrohetd348b6e2010-12-20 08:22:47 -0800637 }
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800638 });
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700639 }
640
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800641 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000642 /*package*/ static void native_drawPaint(long nativeCanvas, long paint) {
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700643 // FIXME
Xavier Ducrohet8a80a852011-02-09 19:39:52 -0800644 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
645 "Canvas.drawPaint is not supported.", null, null /*data*/);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700646 }
647
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800648 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000649 /*package*/ static void native_drawLine(long nativeCanvas,
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800650 final float startX, final float startY, final float stopX, final float stopY,
Narayan Kamath84151432014-01-27 14:24:16 +0000651 long paint) {
Xavier Ducrohet251d2e92010-11-01 22:02:08 -0700652
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800653 draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
654 new GcSnapshot.Drawable() {
Xavier Ducrohet46d43cc2012-02-02 15:44:50 -0800655 @Override
Xavier Ducrohet9d765812011-03-14 15:12:21 -0700656 public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800657 graphics.drawLine((int)startX, (int)startY, (int)stopX, (int)stopY);
658 }
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800659 });
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700660 }
661
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800662 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000663 /*package*/ static void native_drawRect(long nativeCanvas, RectF rect, long paint) {
Xavier Ducrohet251d2e92010-11-01 22:02:08 -0700664 native_drawRect(nativeCanvas, rect.left, rect.top, rect.right, rect.bottom, paint);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700665 }
666
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800667 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000668 /*package*/ static void native_drawRect(long nativeCanvas,
669 final float left, final float top, final float right, final float bottom, long paint) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700670
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800671 draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
672 new GcSnapshot.Drawable() {
Xavier Ducrohet46d43cc2012-02-02 15:44:50 -0800673 @Override
Xavier Ducrohet9d765812011-03-14 15:12:21 -0700674 public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
675 int style = paintDelegate.getStyle();
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700676
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800677 // draw
678 if (style == Paint.Style.FILL.nativeInt ||
679 style == Paint.Style.FILL_AND_STROKE.nativeInt) {
680 graphics.fillRect((int)left, (int)top,
681 (int)(right-left), (int)(bottom-top));
682 }
Xavier Ducrohetcfdc7842010-12-14 18:05:22 -0800683
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800684 if (style == Paint.Style.STROKE.nativeInt ||
685 style == Paint.Style.FILL_AND_STROKE.nativeInt) {
686 graphics.drawRect((int)left, (int)top,
687 (int)(right-left), (int)(bottom-top));
688 }
689 }
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800690 });
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700691 }
692
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800693 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000694 /*package*/ static void native_drawOval(long nativeCanvas, final RectF oval, long paint) {
Xavier Ducrohet251d2e92010-11-01 22:02:08 -0700695 if (oval.right > oval.left && oval.bottom > oval.top) {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800696 draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
697 new GcSnapshot.Drawable() {
Xavier Ducrohet46d43cc2012-02-02 15:44:50 -0800698 @Override
Xavier Ducrohet9d765812011-03-14 15:12:21 -0700699 public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
700 int style = paintDelegate.getStyle();
Xavier Ducrohet251d2e92010-11-01 22:02:08 -0700701
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800702 // draw
703 if (style == Paint.Style.FILL.nativeInt ||
704 style == Paint.Style.FILL_AND_STROKE.nativeInt) {
705 graphics.fillOval((int)oval.left, (int)oval.top,
706 (int)oval.width(), (int)oval.height());
707 }
Xavier Ducrohet251d2e92010-11-01 22:02:08 -0700708
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800709 if (style == Paint.Style.STROKE.nativeInt ||
710 style == Paint.Style.FILL_AND_STROKE.nativeInt) {
711 graphics.drawOval((int)oval.left, (int)oval.top,
712 (int)oval.width(), (int)oval.height());
713 }
714 }
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800715 });
Xavier Ducrohet251d2e92010-11-01 22:02:08 -0700716 }
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700717 }
718
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800719 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000720 /*package*/ static void native_drawCircle(long nativeCanvas,
721 float cx, float cy, float radius, long paint) {
Xavier Ducrohet251d2e92010-11-01 22:02:08 -0700722 native_drawOval(nativeCanvas,
Xavier Ducrohet5bf28022012-01-18 17:08:53 -0800723 new RectF(cx - radius, cy - radius, cx + radius, cy + radius),
Xavier Ducrohet251d2e92010-11-01 22:02:08 -0700724 paint);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700725 }
726
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800727 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000728 /*package*/ static void native_drawArc(long nativeCanvas,
Xavier Ducrohet9d765812011-03-14 15:12:21 -0700729 final RectF oval, final float startAngle, final float sweep,
Narayan Kamath84151432014-01-27 14:24:16 +0000730 final boolean useCenter, long paint) {
Xavier Ducrohet9d765812011-03-14 15:12:21 -0700731 if (oval.right > oval.left && oval.bottom > oval.top) {
732 draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
733 new GcSnapshot.Drawable() {
Xavier Ducrohet46d43cc2012-02-02 15:44:50 -0800734 @Override
Xavier Ducrohet9d765812011-03-14 15:12:21 -0700735 public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
736 int style = paintDelegate.getStyle();
737
738 Arc2D.Float arc = new Arc2D.Float(
739 oval.left, oval.top, oval.width(), oval.height(),
740 -startAngle, -sweep,
741 useCenter ? Arc2D.PIE : Arc2D.OPEN);
742
743 // draw
744 if (style == Paint.Style.FILL.nativeInt ||
745 style == Paint.Style.FILL_AND_STROKE.nativeInt) {
746 graphics.fill(arc);
747 }
748
749 if (style == Paint.Style.STROKE.nativeInt ||
750 style == Paint.Style.FILL_AND_STROKE.nativeInt) {
751 graphics.draw(arc);
752 }
753 }
754 });
755 }
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700756 }
757
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800758 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000759 /*package*/ static void native_drawRoundRect(long nativeCanvas,
760 final RectF rect, final float rx, final float ry, long paint) {
Xavier Ducrohet251d2e92010-11-01 22:02:08 -0700761
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800762 draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
763 new GcSnapshot.Drawable() {
Xavier Ducrohet46d43cc2012-02-02 15:44:50 -0800764 @Override
Xavier Ducrohet9d765812011-03-14 15:12:21 -0700765 public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
766 int style = paintDelegate.getStyle();
Xavier Ducrohet251d2e92010-11-01 22:02:08 -0700767
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800768 // draw
769 if (style == Paint.Style.FILL.nativeInt ||
770 style == Paint.Style.FILL_AND_STROKE.nativeInt) {
771 graphics.fillRoundRect(
772 (int)rect.left, (int)rect.top,
773 (int)rect.width(), (int)rect.height(),
774 (int)rx, (int)ry);
775 }
Xavier Ducrohet251d2e92010-11-01 22:02:08 -0700776
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800777 if (style == Paint.Style.STROKE.nativeInt ||
778 style == Paint.Style.FILL_AND_STROKE.nativeInt) {
779 graphics.drawRoundRect(
780 (int)rect.left, (int)rect.top,
781 (int)rect.width(), (int)rect.height(),
782 (int)rx, (int)ry);
783 }
784 }
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800785 });
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700786 }
787
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800788 @LayoutlibDelegate
Narayan Kamath40582002014-01-29 15:05:03 +0000789 /*package*/ static void native_drawPath(long nativeCanvas, long path, long paint) {
Xavier Ducrohetd348b6e2010-12-20 08:22:47 -0800790 final Path_Delegate pathDelegate = Path_Delegate.getDelegate(path);
791 if (pathDelegate == null) {
Xavier Ducrohetd348b6e2010-12-20 08:22:47 -0800792 return;
793 }
794
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800795 draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
796 new GcSnapshot.Drawable() {
Xavier Ducrohet46d43cc2012-02-02 15:44:50 -0800797 @Override
Xavier Ducrohet9d765812011-03-14 15:12:21 -0700798 public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800799 Shape shape = pathDelegate.getJavaShape();
Xavier Ducrohet9d765812011-03-14 15:12:21 -0700800 int style = paintDelegate.getStyle();
Xavier Ducrohetd348b6e2010-12-20 08:22:47 -0800801
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800802 if (style == Paint.Style.FILL.nativeInt ||
803 style == Paint.Style.FILL_AND_STROKE.nativeInt) {
804 graphics.fill(shape);
805 }
Xavier Ducrohetd348b6e2010-12-20 08:22:47 -0800806
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800807 if (style == Paint.Style.STROKE.nativeInt ||
808 style == Paint.Style.FILL_AND_STROKE.nativeInt) {
809 graphics.draw(shape);
810 }
811 }
Xavier Ducrohetd348b6e2010-12-20 08:22:47 -0800812 });
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700813 }
814
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800815 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000816 /*package*/ static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, long bitmap,
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700817 float left, float top,
Narayan Kamath84151432014-01-27 14:24:16 +0000818 long nativePaintOrZero,
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700819 int canvasDensity,
820 int screenDensity,
821 int bitmapDensity) {
Xavier Ducrohetd348b6e2010-12-20 08:22:47 -0800822 // get the delegate from the native int.
823 Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
824 if (bitmapDelegate == null) {
Xavier Ducrohetd348b6e2010-12-20 08:22:47 -0800825 return;
826 }
827
828 BufferedImage image = bitmapDelegate.getImage();
829 float right = left + image.getWidth();
830 float bottom = top + image.getHeight();
831
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800832 drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero,
Xavier Ducrohetd348b6e2010-12-20 08:22:47 -0800833 0, 0, image.getWidth(), image.getHeight(),
834 (int)left, (int)top, (int)right, (int)bottom);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700835 }
836
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800837 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000838 /*package*/ static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, long bitmap,
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700839 Rect src, RectF dst,
Narayan Kamath84151432014-01-27 14:24:16 +0000840 long nativePaintOrZero,
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700841 int screenDensity,
842 int bitmapDensity) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700843 // get the delegate from the native int.
844 Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
845 if (bitmapDelegate == null) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700846 return;
847 }
848
849 BufferedImage image = bitmapDelegate.getImage();
850
851 if (src == null) {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800852 drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero,
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700853 0, 0, image.getWidth(), image.getHeight(),
854 (int)dst.left, (int)dst.top, (int)dst.right, (int)dst.bottom);
855 } else {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800856 drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero,
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700857 src.left, src.top, src.width(), src.height(),
858 (int)dst.left, (int)dst.top, (int)dst.right, (int)dst.bottom);
859 }
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700860 }
861
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800862 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000863 /*package*/ static void native_drawBitmap(long nativeCanvas, long bitmap,
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700864 Rect src, Rect dst,
Narayan Kamath84151432014-01-27 14:24:16 +0000865 long nativePaintOrZero,
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700866 int screenDensity,
867 int bitmapDensity) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700868 // get the delegate from the native int.
869 Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
870 if (bitmapDelegate == null) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700871 return;
872 }
873
874 BufferedImage image = bitmapDelegate.getImage();
875
876 if (src == null) {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800877 drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero,
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700878 0, 0, image.getWidth(), image.getHeight(),
879 dst.left, dst.top, dst.right, dst.bottom);
880 } else {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800881 drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero,
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700882 src.left, src.top, src.width(), src.height(),
883 dst.left, dst.top, dst.right, dst.bottom);
884 }
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700885 }
886
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800887 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000888 /*package*/ static void native_drawBitmap(long nativeCanvas, int[] colors,
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800889 int offset, int stride, final float x,
890 final float y, int width, int height,
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700891 boolean hasAlpha,
Narayan Kamath84151432014-01-27 14:24:16 +0000892 long nativePaintOrZero) {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800893
894 // create a temp BufferedImage containing the content.
895 final BufferedImage image = new BufferedImage(width, height,
896 hasAlpha ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB);
897 image.setRGB(0, 0, width, height, colors, offset, stride);
898
899 draw(nativeCanvas, nativePaintOrZero, true /*compositeOnly*/, false /*forceSrcMode*/,
900 new GcSnapshot.Drawable() {
Xavier Ducrohet46d43cc2012-02-02 15:44:50 -0800901 @Override
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800902 public void draw(Graphics2D graphics, Paint_Delegate paint) {
903 if (paint != null && paint.isFilterBitmap()) {
904 graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
905 RenderingHints.VALUE_INTERPOLATION_BILINEAR);
906 }
907
908 graphics.drawImage(image, (int) x, (int) y, null);
909 }
910 });
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700911 }
912
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800913 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000914 /*package*/ static void nativeDrawBitmapMatrix(long nCanvas, long nBitmap,
915 long nMatrix, long nPaint) {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800916 // get the delegate from the native int.
917 Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
918 if (canvasDelegate == null) {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800919 return;
920 }
921
Xavier Ducrohetd43909c2010-12-23 07:16:21 -0800922 // get the delegate from the native int, which can be null
923 Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nPaint);
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800924
925 // get the delegate from the native int.
926 Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(nBitmap);
927 if (bitmapDelegate == null) {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800928 return;
929 }
930
931 final BufferedImage image = getImageToDraw(bitmapDelegate, paintDelegate, sBoolOut);
932
933 Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(nMatrix);
934 if (matrixDelegate == null) {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800935 return;
936 }
937
938 final AffineTransform mtx = matrixDelegate.getAffineTransform();
939
940 canvasDelegate.getSnapshot().draw(new GcSnapshot.Drawable() {
Xavier Ducrohet46d43cc2012-02-02 15:44:50 -0800941 @Override
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800942 public void draw(Graphics2D graphics, Paint_Delegate paint) {
943 if (paint != null && paint.isFilterBitmap()) {
944 graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
945 RenderingHints.VALUE_INTERPOLATION_BILINEAR);
946 }
947
948 //FIXME add support for canvas, screen and bitmap densities.
949 graphics.drawImage(image, mtx, null);
950 }
951 }, paintDelegate, true /*compositeOnly*/, false /*forceSrcMode*/);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700952 }
953
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800954 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000955 /*package*/ static void nativeDrawBitmapMesh(long nCanvas, long nBitmap,
Xavier Ducrohet8a80a852011-02-09 19:39:52 -0800956 int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors,
Narayan Kamath84151432014-01-27 14:24:16 +0000957 int colorOffset, long nPaint) {
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700958 // FIXME
Xavier Ducrohet8a80a852011-02-09 19:39:52 -0800959 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
960 "Canvas.drawBitmapMesh is not supported.", null, null /*data*/);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700961 }
962
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800963 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000964 /*package*/ static void nativeDrawVertices(long nCanvas, int mode, int n,
Xavier Ducrohet8a80a852011-02-09 19:39:52 -0800965 float[] verts, int vertOffset,
966 float[] texs, int texOffset,
967 int[] colors, int colorOffset,
968 short[] indices, int indexOffset,
Narayan Kamath84151432014-01-27 14:24:16 +0000969 int indexCount, long nPaint) {
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700970 // FIXME
Xavier Ducrohet8a80a852011-02-09 19:39:52 -0800971 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
972 "Canvas.drawVertices is not supported.", null, null /*data*/);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700973 }
974
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800975 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +0000976 /*package*/ static void native_drawText(long nativeCanvas,
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800977 final char[] text, final int index, final int count,
Narayan Kamath84151432014-01-27 14:24:16 +0000978 final float startX, final float startY, final int flags, long paint) {
Deepanshu Gupta0d9c9222013-07-12 11:38:05 -0700979
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800980 draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
981 new GcSnapshot.Drawable() {
Xavier Ducrohet46d43cc2012-02-02 15:44:50 -0800982 @Override
Xavier Ducrohet9d765812011-03-14 15:12:21 -0700983 public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
Xavier Ducrohetc6083f22011-02-23 09:53:56 -0800984 // WARNING: the logic in this method is similar to Paint_Delegate.measureText.
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800985 // Any change to this method should be reflected in Paint.measureText
986 // Paint.TextAlign indicates how the text is positioned relative to X.
987 // LEFT is the default and there's nothing to do.
988 float x = startX;
Deepanshu Gupta0d9c9222013-07-12 11:38:05 -0700989 int limit = index + count;
990 boolean isRtl = flags == Canvas.DIRECTION_RTL;
Xavier Ducrohet9d765812011-03-14 15:12:21 -0700991 if (paintDelegate.getTextAlign() != Paint.Align.LEFT.nativeInt) {
Deepanshu Gupta5ad7c182014-01-07 11:58:44 -0800992 RectF bounds = paintDelegate.measureText(text, index, count, isRtl);
993 float m = bounds.right - bounds.left;
Xavier Ducrohet9d765812011-03-14 15:12:21 -0700994 if (paintDelegate.getTextAlign() == Paint.Align.CENTER.nativeInt) {
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800995 x -= m / 2;
Xavier Ducrohet9d765812011-03-14 15:12:21 -0700996 } else if (paintDelegate.getTextAlign() == Paint.Align.RIGHT.nativeInt) {
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800997 x -= m;
Xavier Ducrohet5802dea2010-11-01 16:17:18 -0700998 }
Xavier Ducrohetd38e7762010-12-21 06:20:28 -0800999 }
Xavier Ducrohet5802dea2010-11-01 16:17:18 -07001000
Deepanshu Gupta0d9c9222013-07-12 11:38:05 -07001001 new BidiRenderer(graphics, paintDelegate, text).renderText(
1002 index, limit, isRtl, null, 0, true, x, startY);
Xavier Ducrohet5802dea2010-11-01 16:17:18 -07001003 }
Xavier Ducrohetd38e7762010-12-21 06:20:28 -08001004 });
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -07001005 }
1006
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -08001007 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +00001008 /*package*/ static void native_drawText(long nativeCanvas, String text,
1009 int start, int end, float x, float y, final int flags, long paint) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -07001010 int count = end - start;
1011 char[] buffer = TemporaryBuffer.obtain(count);
1012 TextUtils.getChars(text, start, end, buffer, 0);
1013
1014 native_drawText(nativeCanvas, buffer, 0, count, x, y, flags, paint);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -07001015 }
1016
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -08001017 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +00001018 /*package*/ static void native_drawTextRun(long nativeCanvas, String text,
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -07001019 int start, int end, int contextStart, int contextEnd,
Narayan Kamath84151432014-01-27 14:24:16 +00001020 float x, float y, int flags, long paint) {
Xavier Ducrohete0c763f2010-11-04 18:04:27 -07001021 int count = end - start;
1022 char[] buffer = TemporaryBuffer.obtain(count);
1023 TextUtils.getChars(text, start, end, buffer, 0);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -07001024
Xavier Ducroheta4510a72011-02-24 18:56:34 -08001025 native_drawText(nativeCanvas, buffer, 0, count, x, y, flags, paint);
Xavier Ducrohete0c763f2010-11-04 18:04:27 -07001026 }
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -07001027
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -08001028 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +00001029 /*package*/ static void native_drawTextRun(long nativeCanvas, char[] text,
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -07001030 int start, int count, int contextStart, int contextCount,
Narayan Kamath84151432014-01-27 14:24:16 +00001031 float x, float y, int flags, long paint) {
Xavier Ducrohetbbefc862011-01-13 18:02:08 -08001032 native_drawText(nativeCanvas, text, start, count, x, y, flags, paint);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -07001033 }
1034
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -08001035 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +00001036 /*package*/ static void native_drawPosText(long nativeCanvas,
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -07001037 char[] text, int index,
1038 int count, float[] pos,
Narayan Kamath84151432014-01-27 14:24:16 +00001039 long paint) {
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -07001040 // FIXME
Xavier Ducrohet8a80a852011-02-09 19:39:52 -08001041 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
1042 "Canvas.drawPosText is not supported.", null, null /*data*/);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -07001043 }
1044
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -08001045 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +00001046 /*package*/ static void native_drawPosText(long nativeCanvas,
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -07001047 String text, float[] pos,
Narayan Kamath84151432014-01-27 14:24:16 +00001048 long paint) {
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -07001049 // FIXME
Xavier Ducrohet8a80a852011-02-09 19:39:52 -08001050 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
1051 "Canvas.drawPosText is not supported.", null, null /*data*/);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -07001052 }
1053
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -08001054 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +00001055 /*package*/ static void native_drawTextOnPath(long nativeCanvas,
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -07001056 char[] text, int index,
Narayan Kamath84151432014-01-27 14:24:16 +00001057 int count, long path,
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -07001058 float hOffset,
1059 float vOffset, int bidiFlags,
Narayan Kamath84151432014-01-27 14:24:16 +00001060 long paint) {
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -07001061 // FIXME
Xavier Ducrohet8a80a852011-02-09 19:39:52 -08001062 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
1063 "Canvas.drawTextOnPath is not supported.", null, null /*data*/);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -07001064 }
1065
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -08001066 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +00001067 /*package*/ static void native_drawTextOnPath(long nativeCanvas,
1068 String text, long path,
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -07001069 float hOffset,
1070 float vOffset,
Narayan Kamath84151432014-01-27 14:24:16 +00001071 int flags, long paint) {
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -07001072 // FIXME
Xavier Ducrohet8a80a852011-02-09 19:39:52 -08001073 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
1074 "Canvas.drawTextOnPath is not supported.", null, null /*data*/);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -07001075 }
1076
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -08001077 @LayoutlibDelegate
Narayan Kamath84151432014-01-27 14:24:16 +00001078 /*package*/ static void finalizer(long nativeCanvas) {
Xavier Ducrohet9eb6d412010-12-01 12:28:43 -08001079 // get the delegate from the native int so that it can be disposed.
1080 Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
1081 if (canvasDelegate == null) {
Xavier Ducrohet9eb6d412010-12-01 12:28:43 -08001082 return;
1083 }
1084
1085 canvasDelegate.dispose();
1086
1087 // remove it from the manager.
Xavier Ducrohetcc4977d2011-02-22 11:54:37 -08001088 sManager.removeJavaReferenceFor(nativeCanvas);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -07001089 }
1090
1091 // ---- Private delegate/helper methods ----
1092
Xavier Ducrohetd348b6e2010-12-20 08:22:47 -08001093 /**
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -08001094 * Executes a {@link GcSnapshot.Drawable} with a given canvas and paint.
Xavier Ducrohetd38e7762010-12-21 06:20:28 -08001095 * <p>Note that the drawable may actually be executed several times if there are
1096 * layers involved (see {@link #saveLayer(RectF, int, int)}.
Xavier Ducrohetd348b6e2010-12-20 08:22:47 -08001097 */
Narayan Kamath84151432014-01-27 14:24:16 +00001098 private static void draw(long nCanvas, long nPaint, boolean compositeOnly, boolean forceSrcMode,
Xavier Ducrohetd38e7762010-12-21 06:20:28 -08001099 GcSnapshot.Drawable drawable) {
Xavier Ducrohetd348b6e2010-12-20 08:22:47 -08001100 // get the delegate from the native int.
1101 Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
1102 if (canvasDelegate == null) {
Xavier Ducrohetd348b6e2010-12-20 08:22:47 -08001103 return;
1104 }
1105
Xavier Ducrohetd43909c2010-12-23 07:16:21 -08001106 // get the paint which can be null if nPaint is 0;
1107 Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nPaint);
Xavier Ducrohetd38e7762010-12-21 06:20:28 -08001108
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -08001109 canvasDelegate.getSnapshot().draw(drawable, paintDelegate, compositeOnly, forceSrcMode);
Xavier Ducrohetd38e7762010-12-21 06:20:28 -08001110 }
1111
1112 /**
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -08001113 * Executes a {@link GcSnapshot.Drawable} with a given canvas. No paint object will be provided
Xavier Ducrohetd38e7762010-12-21 06:20:28 -08001114 * to {@link GcSnapshot.Drawable#draw(Graphics2D, Paint_Delegate)}.
1115 * <p>Note that the drawable may actually be executed several times if there are
1116 * layers involved (see {@link #saveLayer(RectF, int, int)}.
1117 */
Narayan Kamath84151432014-01-27 14:24:16 +00001118 private static void draw(long nCanvas, GcSnapshot.Drawable drawable) {
Xavier Ducrohetd38e7762010-12-21 06:20:28 -08001119 // get the delegate from the native int.
1120 Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
1121 if (canvasDelegate == null) {
Xavier Ducrohetd348b6e2010-12-20 08:22:47 -08001122 return;
1123 }
1124
Xavier Ducrohetd38e7762010-12-21 06:20:28 -08001125 canvasDelegate.mSnapshot.draw(drawable);
Xavier Ducrohetd348b6e2010-12-20 08:22:47 -08001126 }
1127
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -08001128 private Canvas_Delegate(Bitmap_Delegate bitmap) {
1129 mSnapshot = GcSnapshot.createDefaultSnapshot(mBitmap = bitmap);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -07001130 }
1131
1132 private Canvas_Delegate() {
Xavier Ducrohetd38e7762010-12-21 06:20:28 -08001133 mSnapshot = GcSnapshot.createDefaultSnapshot(null /*image*/);
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -07001134 }
1135
Xavier Ducrohet9eb6d412010-12-01 12:28:43 -08001136 /**
1137 * Disposes of the {@link Graphics2D} stack.
1138 */
1139 private void dispose() {
Xavier Ducrohetcfdc7842010-12-14 18:05:22 -08001140 mSnapshot.dispose();
Xavier Ducrohet9eb6d412010-12-01 12:28:43 -08001141 }
1142
Xavier Ducrohetcfdc7842010-12-14 18:05:22 -08001143 private int save(int saveFlags) {
1144 // get the current save count
1145 int count = mSnapshot.size();
1146
Xavier Ducrohetd38e7762010-12-21 06:20:28 -08001147 mSnapshot = mSnapshot.save(saveFlags);
1148
1149 // return the old save count
1150 return count;
1151 }
1152
1153 private int saveLayerAlpha(RectF rect, int alpha, int saveFlags) {
1154 Paint_Delegate paint = new Paint_Delegate();
1155 paint.setAlpha(alpha);
1156 return saveLayer(rect, paint, saveFlags);
1157 }
1158
1159 private int saveLayer(RectF rect, Paint_Delegate paint, int saveFlags) {
1160 // get the current save count
1161 int count = mSnapshot.size();
1162
1163 mSnapshot = mSnapshot.saveLayer(rect, paint, saveFlags);
Xavier Ducrohetcfdc7842010-12-14 18:05:22 -08001164
1165 // return the old save count
1166 return count;
1167 }
1168
1169 /**
1170 * Restores the {@link GcSnapshot} to <var>saveCount</var>
1171 * @param saveCount the saveCount
1172 */
1173 private void restoreTo(int saveCount) {
1174 mSnapshot = mSnapshot.restoreTo(saveCount);
1175 }
1176
1177 /**
1178 * Restores the {@link GcSnapshot} to <var>saveCount</var>
1179 * @param saveCount the saveCount
1180 */
1181 private void restore() {
1182 mSnapshot = mSnapshot.restore();
1183 }
1184
1185 private boolean clipRect(float left, float top, float right, float bottom, int regionOp) {
1186 return mSnapshot.clipRect(left, top, right, bottom, regionOp);
Xavier Ducrohet8da363142010-12-13 16:42:01 -08001187 }
1188
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -08001189 private void setBitmap(Bitmap_Delegate bitmap) {
1190 mBitmap = bitmap;
Xavier Ducrohetcfdc7842010-12-14 18:05:22 -08001191 assert mSnapshot.size() == 1;
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -08001192 mSnapshot.setBitmap(mBitmap);
Xavier Ducrohet5802dea2010-11-01 16:17:18 -07001193 }
1194
Xavier Ducrohet5802dea2010-11-01 16:17:18 -07001195 private static void drawBitmap(
Narayan Kamath84151432014-01-27 14:24:16 +00001196 long nativeCanvas,
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -08001197 Bitmap_Delegate bitmap,
Narayan Kamath84151432014-01-27 14:24:16 +00001198 long nativePaintOrZero,
Xavier Ducrohetd38e7762010-12-21 06:20:28 -08001199 final int sleft, final int stop, final int sright, final int sbottom,
1200 final int dleft, final int dtop, final int dright, final int dbottom) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -07001201 // get the delegate from the native int.
1202 Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
1203 if (canvasDelegate == null) {
Xavier Ducrohet5802dea2010-11-01 16:17:18 -07001204 return;
1205 }
1206
Xavier Ducrohetd43909c2010-12-23 07:16:21 -08001207 // get the paint, which could be null if the int is 0
1208 Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nativePaintOrZero);
Xavier Ducrohet5802dea2010-11-01 16:17:18 -07001209
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -08001210 final BufferedImage image = getImageToDraw(bitmap, paintDelegate, sBoolOut);
Xavier Ducrohet5802dea2010-11-01 16:17:18 -07001211
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -08001212 draw(nativeCanvas, nativePaintOrZero, true /*compositeOnly*/, sBoolOut[0],
Xavier Ducrohetd38e7762010-12-21 06:20:28 -08001213 new GcSnapshot.Drawable() {
Xavier Ducrohet46d43cc2012-02-02 15:44:50 -08001214 @Override
Xavier Ducrohetd38e7762010-12-21 06:20:28 -08001215 public void draw(Graphics2D graphics, Paint_Delegate paint) {
1216 if (paint != null && paint.isFilterBitmap()) {
1217 graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
1218 RenderingHints.VALUE_INTERPOLATION_BILINEAR);
1219 }
1220
1221 //FIXME add support for canvas, screen and bitmap densities.
1222 graphics.drawImage(image, dleft, dtop, dright, dbottom,
1223 sleft, stop, sright, sbottom, null);
1224 }
1225 });
Xavier Ducrohet5802dea2010-11-01 16:17:18 -07001226 }
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -08001227
1228
1229 /**
1230 * Returns a BufferedImage ready for drawing, based on the bitmap and paint delegate.
1231 * The image returns, through a 1-size boolean array, whether the drawing code should
1232 * use a SRC composite no matter what the paint says.
1233 *
1234 * @param bitmap the bitmap
1235 * @param paint the paint that will be used to draw
1236 * @param forceSrcMode whether the composite will have to be SRC
1237 * @return the image to draw
1238 */
1239 private static BufferedImage getImageToDraw(Bitmap_Delegate bitmap, Paint_Delegate paint,
1240 boolean[] forceSrcMode) {
1241 BufferedImage image = bitmap.getImage();
1242 forceSrcMode[0] = false;
1243
1244 // if the bitmap config is alpha_8, then we erase all color value from it
1245 // before drawing it.
1246 if (bitmap.getConfig() == Bitmap.Config.ALPHA_8) {
1247 fixAlpha8Bitmap(image);
1248 } else if (bitmap.hasAlpha() == false) {
1249 // hasAlpha is merely a rendering hint. There can in fact be alpha values
1250 // in the bitmap but it should be ignored at drawing time.
1251 // There is two ways to do this:
1252 // - override the composite to be SRC. This can only be used if the composite
1253 // was going to be SRC or SRC_OVER in the first place
1254 // - Create a different bitmap to draw in which all the alpha channel values is set
1255 // to 0xFF.
1256 if (paint != null) {
Xavier Ducrohetd43909c2010-12-23 07:16:21 -08001257 Xfermode_Delegate xfermodeDelegate = paint.getXfermode();
1258 if (xfermodeDelegate instanceof PorterDuffXfermode_Delegate) {
1259 PorterDuff.Mode mode =
1260 ((PorterDuffXfermode_Delegate)xfermodeDelegate).getMode();
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -08001261
Xavier Ducrohetd43909c2010-12-23 07:16:21 -08001262 forceSrcMode[0] = mode == PorterDuff.Mode.SRC_OVER ||
1263 mode == PorterDuff.Mode.SRC;
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -08001264 }
1265 }
1266
1267 // if we can't force SRC mode, then create a temp bitmap of TYPE_RGB
1268 if (forceSrcMode[0] == false) {
1269 image = Bitmap_Delegate.createCopy(image, BufferedImage.TYPE_INT_RGB, 0xFF);
1270 }
1271 }
1272
1273 return image;
1274 }
1275
1276 private static void fixAlpha8Bitmap(final BufferedImage image) {
1277 int w = image.getWidth();
1278 int h = image.getHeight();
1279 int[] argb = new int[w * h];
1280 image.getRGB(0, 0, image.getWidth(), image.getHeight(), argb, 0, image.getWidth());
1281
1282 final int length = argb.length;
1283 for (int i = 0 ; i < length; i++) {
1284 argb[i] &= 0xFF000000;
1285 }
1286 image.setRGB(0, 0, w, h, argb, 0, w);
1287 }
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -07001288}
Xavier Ducrohet5802dea2010-11-01 16:17:18 -07001289