1d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet/*
2d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet * Copyright (C) 2010 The Android Open Source Project
3d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet *
4d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet * Licensed under the Apache License, Version 2.0 (the "License");
5d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet * you may not use this file except in compliance with the License.
6d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet * You may obtain a copy of the License at
7d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet *
8d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet *      http://www.apache.org/licenses/LICENSE-2.0
9d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet *
10d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet * Unless required by applicable law or agreed to in writing, software
11d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet * distributed under the License is distributed on an "AS IS" BASIS,
12d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet * See the License for the specific language governing permissions and
14d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet * limitations under the License.
15d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet */
16d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
17d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohetpackage android.graphics;
18d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
19918aaa5717fce6081557c82ce1c439b6922737d5Xavier Ducrohetimport com.android.ide.common.rendering.api.LayoutLog;
20d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohetimport com.android.layoutlib.bridge.Bridge;
21d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohetimport com.android.layoutlib.bridge.impl.DelegateManager;
229a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohetimport com.android.tools.layoutlib.annotations.LayoutlibDelegate;
23d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
24d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohetimport android.graphics.Path.Direction;
25d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohetimport android.graphics.Path.FillType;
26d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
27d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohetimport java.awt.Shape;
28d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohetimport java.awt.geom.AffineTransform;
29d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohetimport java.awt.geom.Arc2D;
30d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohetimport java.awt.geom.Area;
31c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohetimport java.awt.geom.Ellipse2D;
32d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohetimport java.awt.geom.GeneralPath;
33d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohetimport java.awt.geom.PathIterator;
34d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohetimport java.awt.geom.Point2D;
35d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohetimport java.awt.geom.Rectangle2D;
36c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohetimport java.awt.geom.RoundRectangle2D;
37d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
38d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet/**
39d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet * Delegate implementing the native methods of android.graphics.Path
40d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet *
41d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet * Through the layoutlib_create tool, the original native methods of Path have been replaced
42d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet * by calls to methods of the same name in this delegate class.
43d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet *
44d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet * This class behaves like the original native implementation, but in Java, keeping previously
45d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet * native data into its own objects and mapping them to int that are sent back and forth between
46d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet * it and the original Path class.
47d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet *
48d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet * @see DelegateManager
49d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet *
50d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet */
51d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohetpublic final class Path_Delegate {
52d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
53d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    // ---- delegate manager ----
54d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    private static final DelegateManager<Path_Delegate> sManager =
55f0a53435f14d23d9555fc46014352ee6a7baa647Xavier Ducrohet            new DelegateManager<Path_Delegate>(Path_Delegate.class);
56d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
57d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    // ---- delegate data ----
58d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    private FillType mFillType = FillType.WINDING;
59d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    private GeneralPath mPath = new GeneralPath();
60d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
61d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    private float mLastX = 0;
62d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    private float mLastY = 0;
63d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
64d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    // ---- Public Helper methods ----
65d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
66d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    public static Path_Delegate getDelegate(int nPath) {
67d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        return sManager.getDelegate(nPath);
68d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
69d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
70d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    public Shape getJavaShape() {
71d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        return mPath;
72d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
73d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
74b44b43b1579486ff7ecd0f7528f17711acdeae98Xavier Ducrohet    public void setJavaShape(Shape shape) {
75b44b43b1579486ff7ecd0f7528f17711acdeae98Xavier Ducrohet        mPath.reset();
76b44b43b1579486ff7ecd0f7528f17711acdeae98Xavier Ducrohet        mPath.append(shape, false /*connect*/);
77b44b43b1579486ff7ecd0f7528f17711acdeae98Xavier Ducrohet    }
78b44b43b1579486ff7ecd0f7528f17711acdeae98Xavier Ducrohet
79b44b43b1579486ff7ecd0f7528f17711acdeae98Xavier Ducrohet    public void reset() {
80b44b43b1579486ff7ecd0f7528f17711acdeae98Xavier Ducrohet        mPath.reset();
81b44b43b1579486ff7ecd0f7528f17711acdeae98Xavier Ducrohet    }
82b44b43b1579486ff7ecd0f7528f17711acdeae98Xavier Ducrohet
83b44b43b1579486ff7ecd0f7528f17711acdeae98Xavier Ducrohet    public void setPathIterator(PathIterator iterator) {
84b44b43b1579486ff7ecd0f7528f17711acdeae98Xavier Ducrohet        mPath.reset();
85b44b43b1579486ff7ecd0f7528f17711acdeae98Xavier Ducrohet        mPath.append(iterator, false /*connect*/);
86b44b43b1579486ff7ecd0f7528f17711acdeae98Xavier Ducrohet    }
87b44b43b1579486ff7ecd0f7528f17711acdeae98Xavier Ducrohet
88d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    // ---- native methods ----
89d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
909a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
91d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /*package*/ static int init1() {
92d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        // create the delegate
93d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        Path_Delegate newDelegate = new Path_Delegate();
94d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
95cc4977d0fdaf657907912fd6cc2f9426dc8d2e36Xavier Ducrohet        return sManager.addNewDelegate(newDelegate);
96d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
97d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
989a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
99d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /*package*/ static int init2(int nPath) {
100d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        // create the delegate
101d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        Path_Delegate newDelegate = new Path_Delegate();
102d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
103d43909c7503e11eb335a452d296a10804bb01fd6Xavier Ducrohet        // get the delegate to copy, which could be null if nPath is 0
104d43909c7503e11eb335a452d296a10804bb01fd6Xavier Ducrohet        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
105d43909c7503e11eb335a452d296a10804bb01fd6Xavier Ducrohet        if (pathDelegate != null) {
106d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            newDelegate.set(pathDelegate);
107d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
108d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
109cc4977d0fdaf657907912fd6cc2f9426dc8d2e36Xavier Ducrohet        return sManager.addNewDelegate(newDelegate);
110d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
111d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
1129a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
113d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /*package*/ static void native_reset(int nPath) {
114d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
115d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (pathDelegate == null) {
116d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            return;
117d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
118d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
119d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        pathDelegate.mPath.reset();
120d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
121d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
1229a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
123d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /*package*/ static void native_rewind(int nPath) {
124d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        // call out to reset since there's nothing to optimize in
125d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        // terms of data structs.
126d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        native_reset(nPath);
127d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
128d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
1299a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
130d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /*package*/ static void native_set(int native_dst, int native_src) {
131d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        Path_Delegate pathDstDelegate = sManager.getDelegate(native_dst);
132d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (pathDstDelegate == null) {
133d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            return;
134d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
135d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
136d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        Path_Delegate pathSrcDelegate = sManager.getDelegate(native_src);
137d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (pathSrcDelegate == null) {
138d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            return;
139d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
140d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
141d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        pathDstDelegate.set(pathSrcDelegate);
142d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
143d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
1449a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
145d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /*package*/ static int native_getFillType(int nPath) {
146d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
147d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (pathDelegate == null) {
148d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            return 0;
149d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
150d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
151d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        return pathDelegate.mFillType.nativeInt;
152d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
153d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
1549a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
155d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /*package*/ static void native_setFillType(int nPath, int ft) {
156d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
157d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (pathDelegate == null) {
158d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            return;
159d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
160d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
161d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        pathDelegate.mFillType = Path.sFillTypeArray[ft];
162d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
163d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
1649a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
165d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /*package*/ static boolean native_isEmpty(int nPath) {
166d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
167d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (pathDelegate == null) {
168d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            return true;
169d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
170d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
171d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        return pathDelegate.isEmpty();
172d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
173d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
1749a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
175d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /*package*/ static boolean native_isRect(int nPath, RectF rect) {
176d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
177d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (pathDelegate == null) {
178d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            return false;
179d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
180d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
181d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        // create an Area that can test if the path is a rect
182d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        Area area = new Area(pathDelegate.mPath);
183d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (area.isRectangular()) {
184d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            if (rect != null) {
185d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet                pathDelegate.fillBounds(rect);
186d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            }
187d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
188d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            return true;
189d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
190d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
191d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        return false;
192d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
193d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
1949a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
195d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /*package*/ static void native_computeBounds(int nPath, RectF bounds) {
196d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
197d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (pathDelegate == null) {
198d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            return;
199d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
200d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
201d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        pathDelegate.fillBounds(bounds);
202d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
203d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
2049a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
205d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /*package*/ static void native_incReserve(int nPath, int extraPtCount) {
206d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        // since we use a java2D path, there's no way to pre-allocate new points,
207d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        // so we do nothing.
208d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
209d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
2109a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
211d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /*package*/ static void native_moveTo(int nPath, float x, float y) {
212d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
213d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (pathDelegate == null) {
214d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            return;
215d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
216d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
217d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        pathDelegate.moveTo(x, y);
218d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
219d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
2209a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
221d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /*package*/ static void native_rMoveTo(int nPath, float dx, float dy) {
222d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
223d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (pathDelegate == null) {
224d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            return;
225d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
226d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
227d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        pathDelegate.rMoveTo(dx, dy);
228d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
229d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
2309a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
231d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /*package*/ static void native_lineTo(int nPath, float x, float y) {
232d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
233d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (pathDelegate == null) {
234d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            return;
235d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
236d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
237d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        pathDelegate.lineTo(x, y);
238d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
239d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
2409a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
241d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /*package*/ static void native_rLineTo(int nPath, float dx, float dy) {
242d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
243d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (pathDelegate == null) {
244d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            return;
245d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
246d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
247d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        pathDelegate.rLineTo(dx, dy);
248d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
249d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
2509a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
251d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /*package*/ static void native_quadTo(int nPath, float x1, float y1, float x2, float y2) {
252d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
253d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (pathDelegate == null) {
254d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            return;
255d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
256d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
257d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        pathDelegate.quadTo(x1, y1, x2, y2);
258d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
259d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
2609a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
261b6e53f481294aec2edac5d83d9fde81827c23bd7Xavier Ducrohet    /*package*/ static void native_rQuadTo(int nPath, float dx1, float dy1, float dx2, float dy2) {
262d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
263d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (pathDelegate == null) {
264d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            return;
265d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
266d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
267d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        pathDelegate.rQuadTo(dx1, dy1, dx2, dy2);
268d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
269d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
2709a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
271d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /*package*/ static void native_cubicTo(int nPath, float x1, float y1,
272b6e53f481294aec2edac5d83d9fde81827c23bd7Xavier Ducrohet            float x2, float y2, float x3, float y3) {
273d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
274d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (pathDelegate == null) {
275d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            return;
276d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
277d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
278d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        pathDelegate.cubicTo(x1, y1, x2, y2, x3, y3);
279d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
280d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
2819a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
282d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /*package*/ static void native_rCubicTo(int nPath, float x1, float y1,
283b6e53f481294aec2edac5d83d9fde81827c23bd7Xavier Ducrohet            float x2, float y2, float x3, float y3) {
284d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
285d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (pathDelegate == null) {
286d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            return;
287d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
288d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
289d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        pathDelegate.rCubicTo(x1, y1, x2, y2, x3, y3);
290d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
291d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
2929a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
293d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /*package*/ static void native_arcTo(int nPath, RectF oval,
294d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet                    float startAngle, float sweepAngle, boolean forceMoveTo) {
295d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
296d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (pathDelegate == null) {
297d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            return;
298d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
299d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
300d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        pathDelegate.arcTo(oval, startAngle, sweepAngle, forceMoveTo);
301d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
302d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
3039a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
304d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /*package*/ static void native_close(int nPath) {
305d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
306d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (pathDelegate == null) {
307d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            return;
308d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
309d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
310d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        pathDelegate.close();
311d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
312d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
3139a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
314d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /*package*/ static void native_addRect(int nPath, RectF rect, int dir) {
315d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
316d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (pathDelegate == null) {
317d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            return;
318d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
319d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
320d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        pathDelegate.addRect(rect.left, rect.top, rect.right, rect.bottom, dir);
321d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
322d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
3239a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
324b6e53f481294aec2edac5d83d9fde81827c23bd7Xavier Ducrohet    /*package*/ static void native_addRect(int nPath,
325b6e53f481294aec2edac5d83d9fde81827c23bd7Xavier Ducrohet            float left, float top, float right, float bottom, int dir) {
326d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
327d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (pathDelegate == null) {
328d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            return;
329d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
330d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
331d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        pathDelegate.addRect(left, top, right, bottom, dir);
332d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
333d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
3349a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
335d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /*package*/ static void native_addOval(int nPath, RectF oval, int dir) {
336c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
337c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        if (pathDelegate == null) {
338c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet            return;
339c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        }
340c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet
341c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        pathDelegate.mPath.append(new Ellipse2D.Float(
342c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet                oval.left, oval.top, oval.width(), oval.height()), false);
343d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
344d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
3459a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
346b6e53f481294aec2edac5d83d9fde81827c23bd7Xavier Ducrohet    /*package*/ static void native_addCircle(int nPath, float x, float y, float radius, int dir) {
347c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
348c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        if (pathDelegate == null) {
349c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet            return;
350c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        }
351c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet
352c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        // because x/y is the center of the circle, need to offset this by the radius
353c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        pathDelegate.mPath.append(new Ellipse2D.Float(
354c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet                x - radius, y - radius, radius * 2, radius * 2), false);
355d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
356d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
3579a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
358d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /*package*/ static void native_addArc(int nPath, RectF oval,
359b6e53f481294aec2edac5d83d9fde81827c23bd7Xavier Ducrohet            float startAngle, float sweepAngle) {
360c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
361c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        if (pathDelegate == null) {
362c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet            return;
363c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        }
364c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet
365c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        // because x/y is the center of the circle, need to offset this by the radius
366c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        pathDelegate.mPath.append(new Arc2D.Float(
367c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet                oval.left, oval.top, oval.width(), oval.height(),
3689d76581faf9eb5f47eff922c14807e51702f363bXavier Ducrohet                -startAngle, -sweepAngle, Arc2D.OPEN), false);
369d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
370d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
3719a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
372c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet    /*package*/ static void native_addRoundRect(
373c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet            int nPath, RectF rect, float rx, float ry, int dir) {
374c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet
375c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
376c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        if (pathDelegate == null) {
377c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet            return;
378c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        }
379c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet
380c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        pathDelegate.mPath.append(new RoundRectangle2D.Float(
381c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet                rect.left, rect.top, rect.width(), rect.height(), rx * 2, ry * 2), false);
382d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
383d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
3849a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
385c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet    /*package*/ static void native_addRoundRect(int nPath, RectF rect, float[] radii, int dir) {
386c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        // Java2D doesn't support different rounded corners in each corner, so just use the
387c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        // first value.
388c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        native_addRoundRect(nPath, rect, radii[0], radii[1], dir);
389c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet
390c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        // there can be a case where this API is used but with similar values for all corners, so
391c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        // in that case we don't warn.
392c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        // we only care if 2 corners are different so just compare to the next one.
393c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        for (int i = 0 ; i < 3 ; i++) {
394c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet            if (radii[i * 2] != radii[(i + 1) * 2] || radii[i * 2 + 1] != radii[(i + 1) * 2 + 1]) {
395c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet                Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
396adaa12cd9e421edf34e36de8cfacc3e3c334bb64Xavier Ducrohet                        "Different corner sizes are not supported in Path.addRoundRect.",
397c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet                        null, null /*data*/);
398c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet                break;
399c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet            }
400c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        }
401d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
402d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
4039a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
404b6e53f481294aec2edac5d83d9fde81827c23bd7Xavier Ducrohet    /*package*/ static void native_addPath(int nPath, int src, float dx, float dy) {
405c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        addPath(nPath, src, AffineTransform.getTranslateInstance(dx, dy));
406d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
407d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
4089a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
409d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /*package*/ static void native_addPath(int nPath, int src) {
410c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        addPath(nPath, src, null /*transform*/);
411d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
412d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
4139a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
414d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /*package*/ static void native_addPath(int nPath, int src, int matrix) {
415c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(matrix);
416c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        if (matrixDelegate == null) {
417c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet            return;
418c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        }
419c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet
420c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        addPath(nPath, src, matrixDelegate.getAffineTransform());
421d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
422d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
4239a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
424b6e53f481294aec2edac5d83d9fde81827c23bd7Xavier Ducrohet    /*package*/ static void native_offset(int nPath, float dx, float dy, int dst_path) {
425d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
426d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (pathDelegate == null) {
427d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            return;
428d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
429d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
430d43909c7503e11eb335a452d296a10804bb01fd6Xavier Ducrohet        // could be null if the int is 0;
431d43909c7503e11eb335a452d296a10804bb01fd6Xavier Ducrohet        Path_Delegate dstDelegate = sManager.getDelegate(dst_path);
432d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
433d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        pathDelegate.offset(dx, dy, dstDelegate);
434d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
435d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
4369a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
437d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /*package*/ static void native_offset(int nPath, float dx, float dy) {
438d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        native_offset(nPath, dx, dy, 0);
439d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
440d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
4419a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
442d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /*package*/ static void native_setLastPoint(int nPath, float dx, float dy) {
443d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
444d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (pathDelegate == null) {
445d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            return;
446d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
447d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
448d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        pathDelegate.mLastX = dx;
449d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        pathDelegate.mLastY = dy;
450d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
451d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
4529a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
453d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /*package*/ static void native_transform(int nPath, int matrix,
454d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet                                                int dst_path) {
455d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
456d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (pathDelegate == null) {
457d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            return;
458d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
459d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
460d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(matrix);
461d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (matrixDelegate == null) {
462d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            return;
463d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
464d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
465d43909c7503e11eb335a452d296a10804bb01fd6Xavier Ducrohet        // this can be null if dst_path is 0
466d43909c7503e11eb335a452d296a10804bb01fd6Xavier Ducrohet        Path_Delegate dstDelegate = sManager.getDelegate(dst_path);
467d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
468d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        pathDelegate.transform(matrixDelegate, dstDelegate);
469d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
470d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
4719a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
472d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /*package*/ static void native_transform(int nPath, int matrix) {
473d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        native_transform(nPath, matrix, 0);
474d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
475d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
4769a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet    @LayoutlibDelegate
477d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /*package*/ static void finalizer(int nPath) {
478cc4977d0fdaf657907912fd6cc2f9426dc8d2e36Xavier Ducrohet        sManager.removeJavaReferenceFor(nPath);
479d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
480d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
481d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
482d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    // ---- Private helper methods ----
483d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
484d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    private void set(Path_Delegate delegate) {
485d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        mPath.reset();
486d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        setFillType(delegate.mFillType);
487d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        mPath.append(delegate.mPath, false /*connect*/);
488d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
489d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
490d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    private void setFillType(FillType fillType) {
491d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        mFillType = fillType;
492d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        mPath.setWindingRule(getWindingRule(fillType));
493d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
494d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
495d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /**
496d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * Returns the Java2D winding rules matching a given Android {@link FillType}.
497d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param type the android fill type
498d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @return the matching java2d winding rule.
499d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     */
500d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    private static int getWindingRule(FillType type) {
501d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        switch (type) {
502d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            case WINDING:
503d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            case INVERSE_WINDING:
504d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet                return GeneralPath.WIND_NON_ZERO;
505d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            case EVEN_ODD:
506d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            case INVERSE_EVEN_ODD:
507d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet                return GeneralPath.WIND_EVEN_ODD;
508d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
509d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
510d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        assert false;
511d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        throw new IllegalArgumentException();
512d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
513d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
514d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    private static Direction getDirection(int direction) {
515d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        for (Direction d : Direction.values()) {
516d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            if (direction == d.nativeInt) {
517d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet                return d;
518d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            }
519d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
520d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
521d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        assert false;
522d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        return null;
523d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
524d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
525c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet    private static void addPath(int destPath, int srcPath, AffineTransform transform) {
526c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        Path_Delegate destPathDelegate = sManager.getDelegate(destPath);
527c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        if (destPathDelegate == null) {
528c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet            return;
529c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        }
530c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet
531c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        Path_Delegate srcPathDelegate = sManager.getDelegate(srcPath);
532c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        if (srcPathDelegate == null) {
533c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet            return;
534c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        }
535c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet
536c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        if (transform != null) {
537c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet            destPathDelegate.mPath.append(
538c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet                    srcPathDelegate.mPath.getPathIterator(transform), false);
539c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        } else {
540c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet            destPathDelegate.mPath.append(srcPathDelegate.mPath, false);
541c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet        }
542c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet    }
543c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet
544c12b4093517ac99cabd91a1bb4bdb3bacfe4bcfdXavier Ducrohet
545d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /**
546d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * Returns whether the path is empty.
547d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @return true if the path is empty.
548d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     */
549d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    private boolean isEmpty() {
550d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        return mPath.getCurrentPoint() == null;
551d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
552d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
553d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /**
554d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * Fills the given {@link RectF} with the path bounds.
555d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param bounds the RectF to be filled.
556d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     */
557d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    private void fillBounds(RectF bounds) {
558d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        Rectangle2D rect = mPath.getBounds2D();
559d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        bounds.left = (float)rect.getMinX();
560d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        bounds.right = (float)rect.getMaxX();
561d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        bounds.top = (float)rect.getMinY();
562d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        bounds.bottom = (float)rect.getMaxY();
563d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
564d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
565d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /**
566d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * Set the beginning of the next contour to the point (x,y).
567d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     *
568d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param x The x-coordinate of the start of a new contour
569d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param y The y-coordinate of the start of a new contour
570d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     */
571d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    private void moveTo(float x, float y) {
572d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        mPath.moveTo(mLastX = x, mLastY = y);
573d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
574d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
575d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /**
576d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * Set the beginning of the next contour relative to the last point on the
577d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * previous contour. If there is no previous contour, this is treated the
578d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * same as moveTo().
579d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     *
580d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param dx The amount to add to the x-coordinate of the end of the
581d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     *           previous contour, to specify the start of a new contour
582d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param dy The amount to add to the y-coordinate of the end of the
583d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     *           previous contour, to specify the start of a new contour
584d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     */
585d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    private void rMoveTo(float dx, float dy) {
586d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        dx += mLastX;
587d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        dy += mLastY;
588d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        mPath.moveTo(mLastX = dx, mLastY = dy);
589d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
590d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
591d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /**
592d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * Add a line from the last point to the specified point (x,y).
593d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * If no moveTo() call has been made for this contour, the first point is
594d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * automatically set to (0,0).
595d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     *
596d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param x The x-coordinate of the end of a line
597d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param y The y-coordinate of the end of a line
598d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     */
599d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    private void lineTo(float x, float y) {
600d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        mPath.lineTo(mLastX = x, mLastY = y);
601d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
602d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
603d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /**
604d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * Same as lineTo, but the coordinates are considered relative to the last
605d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * point on this contour. If there is no previous point, then a moveTo(0,0)
606d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * is inserted automatically.
607d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     *
608d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param dx The amount to add to the x-coordinate of the previous point on
609d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     *           this contour, to specify a line
610d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param dy The amount to add to the y-coordinate of the previous point on
611d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     *           this contour, to specify a line
612d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     */
613d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    private void rLineTo(float dx, float dy) {
614d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (isEmpty()) {
615d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            mPath.moveTo(mLastX = 0, mLastY = 0);
616d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
617d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        dx += mLastX;
618d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        dy += mLastY;
619d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        mPath.lineTo(mLastX = dx, mLastY = dy);
620d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
621d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
622d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /**
623d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * Add a quadratic bezier from the last point, approaching control point
624d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for
625d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * this contour, the first point is automatically set to (0,0).
626d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     *
627d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param x1 The x-coordinate of the control point on a quadratic curve
628d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param y1 The y-coordinate of the control point on a quadratic curve
629d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param x2 The x-coordinate of the end point on a quadratic curve
630d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param y2 The y-coordinate of the end point on a quadratic curve
631d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     */
632d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    private void quadTo(float x1, float y1, float x2, float y2) {
633d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        mPath.quadTo(x1, y1, mLastX = x2, mLastY = y2);
634d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
635d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
636d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /**
637d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * Same as quadTo, but the coordinates are considered relative to the last
638d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * point on this contour. If there is no previous point, then a moveTo(0,0)
639d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * is inserted automatically.
640d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     *
641d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param dx1 The amount to add to the x-coordinate of the last point on
642d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     *            this contour, for the control point of a quadratic curve
643d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param dy1 The amount to add to the y-coordinate of the last point on
644d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     *            this contour, for the control point of a quadratic curve
645d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param dx2 The amount to add to the x-coordinate of the last point on
646d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     *            this contour, for the end point of a quadratic curve
647d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param dy2 The amount to add to the y-coordinate of the last point on
648d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     *            this contour, for the end point of a quadratic curve
649d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     */
650d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    private void rQuadTo(float dx1, float dy1, float dx2, float dy2) {
651d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (isEmpty()) {
652d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            mPath.moveTo(mLastX = 0, mLastY = 0);
653d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
654d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        dx1 += mLastX;
655d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        dy1 += mLastY;
656d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        dx2 += mLastX;
657d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        dy2 += mLastY;
658d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        mPath.quadTo(dx1, dy1, mLastX = dx2, mLastY = dy2);
659d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
660d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
661d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /**
662d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * Add a cubic bezier from the last point, approaching control points
663d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been
664d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * made for this contour, the first point is automatically set to (0,0).
665d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     *
666d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param x1 The x-coordinate of the 1st control point on a cubic curve
667d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param y1 The y-coordinate of the 1st control point on a cubic curve
668d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param x2 The x-coordinate of the 2nd control point on a cubic curve
669d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param y2 The y-coordinate of the 2nd control point on a cubic curve
670d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param x3 The x-coordinate of the end point on a cubic curve
671d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param y3 The y-coordinate of the end point on a cubic curve
672d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     */
673d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    private void cubicTo(float x1, float y1, float x2, float y2,
674d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet                        float x3, float y3) {
675d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        mPath.curveTo(x1, y1, x2, y2, mLastX = x3, mLastY = y3);
676d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
677d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
678d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /**
679d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * Same as cubicTo, but the coordinates are considered relative to the
680d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * current point on this contour. If there is no previous point, then a
681d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * moveTo(0,0) is inserted automatically.
682d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     */
683d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    private void rCubicTo(float dx1, float dy1, float dx2, float dy2,
684d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet                         float dx3, float dy3) {
685d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (isEmpty()) {
686d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            mPath.moveTo(mLastX = 0, mLastY = 0);
687d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
688d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        dx1 += mLastX;
689d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        dy1 += mLastY;
690d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        dx2 += mLastX;
691d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        dy2 += mLastY;
692d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        dx3 += mLastX;
693d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        dy3 += mLastY;
694d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        mPath.curveTo(dx1, dy1, dx2, dy2, mLastX = dx3, mLastY = dy3);
695d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
696d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
697d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /**
698d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * Append the specified arc to the path as a new contour. If the start of
699d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * the path is different from the path's current last point, then an
700d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * automatic lineTo() is added to connect the current contour to the
701d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * start of the arc. However, if the path is empty, then we call moveTo()
702d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * with the first point of the arc. The sweep angle is tread mod 360.
703d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     *
704d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param oval        The bounds of oval defining shape and size of the arc
705d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param startAngle  Starting angle (in degrees) where the arc begins
706d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param sweepAngle  Sweep angle (in degrees) measured clockwise, treated
707d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     *                    mod 360.
708d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param forceMoveTo If true, always begin a new contour with the arc
709d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     */
7109d76581faf9eb5f47eff922c14807e51702f363bXavier Ducrohet    private void arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo) {
7119d76581faf9eb5f47eff922c14807e51702f363bXavier Ducrohet        Arc2D arc = new Arc2D.Float(oval.left, oval.top, oval.width(), oval.height(), -startAngle,
7129d76581faf9eb5f47eff922c14807e51702f363bXavier Ducrohet                -sweepAngle, Arc2D.OPEN);
713d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        mPath.append(arc, true /*connect*/);
714d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
715d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        resetLastPointFromPath();
716d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
717d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
718d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /**
719d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * Close the current contour. If the current point is not equal to the
720d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * first point of the contour, a line segment is automatically added.
721d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     */
722d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    private void close() {
723d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        mPath.closePath();
724d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
725d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
726d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    private void resetLastPointFromPath() {
727d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        Point2D last = mPath.getCurrentPoint();
728d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        mLastX = (float) last.getX();
729d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        mLastY = (float) last.getY();
730d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
731d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
732d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /**
733d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * Add a closed rectangle contour to the path
734d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     *
735d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param left   The left side of a rectangle to add to the path
736d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param top    The top of a rectangle to add to the path
737d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param right  The right side of a rectangle to add to the path
738d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param bottom The bottom of a rectangle to add to the path
739d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param dir    The direction to wind the rectangle's contour
740d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     */
741d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    private void addRect(float left, float top, float right, float bottom,
742d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet                        int dir) {
743d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        moveTo(left, top);
744d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
745d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        Direction direction = getDirection(dir);
746d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
747d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        switch (direction) {
748d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            case CW:
749d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet                lineTo(right, top);
750d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet                lineTo(right, bottom);
751d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet                lineTo(left, bottom);
752d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet                break;
753d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            case CCW:
754d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet                lineTo(left, bottom);
755d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet                lineTo(right, bottom);
756d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet                lineTo(right, top);
757d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet                break;
758d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
759d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
760d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        close();
761d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
762d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        resetLastPointFromPath();
763d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
764d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
765d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /**
766d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * Offset the path by (dx,dy), returning true on success
767d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     *
768d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param dx  The amount in the X direction to offset the entire path
769d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param dy  The amount in the Y direction to offset the entire path
770d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param dst The translated path is written here. If this is null, then
771d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     *            the original path is modified.
772d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     */
773d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    public void offset(float dx, float dy, Path_Delegate dst) {
774d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        GeneralPath newPath = new GeneralPath();
775d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
776d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        PathIterator iterator = mPath.getPathIterator(new AffineTransform(0, 0, dx, 0, 0, dy));
777d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
778d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        newPath.append(iterator, false /*connect*/);
779d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
780d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (dst != null) {
781d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            dst.mPath = newPath;
782d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        } else {
783d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            mPath = newPath;
784d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
785d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
786d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
787d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    /**
788d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * Transform the points in this path by matrix, and write the answer
789d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * into dst. If dst is null, then the the original path is modified.
790d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     *
791d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param matrix The matrix to apply to the path
792d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     * @param dst    The transformed path is written here. If dst is null,
793d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     *               then the the original path is modified
794d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet     */
795d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    public void transform(Matrix_Delegate matrix, Path_Delegate dst) {
796d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (matrix.hasPerspective()) {
797d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            assert false;
798918aaa5717fce6081557c82ce1c439b6922737d5Xavier Ducrohet            Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_AFFINE,
799d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet                    "android.graphics.Path#transform() only " +
80051a7e5447de94791c464cda5cc6ebbf616d73c80Xavier Ducrohet                    "supports affine transformations.", null, null /*data*/);
801d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
802d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
803d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        GeneralPath newPath = new GeneralPath();
804d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
805d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        PathIterator iterator = mPath.getPathIterator(matrix.getAffineTransform());
806d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
807d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        newPath.append(iterator, false /*connect*/);
808d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet
809d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        if (dst != null) {
810d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            dst.mPath = newPath;
811d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        } else {
812d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet            mPath = newPath;
813d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet        }
814d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet    }
815d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet}
816