12d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet/* 22d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * Copyright (C) 2010 The Android Open Source Project 32d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * 42d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * Licensed under the Apache License, Version 2.0 (the "License"); 52d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * you may not use this file except in compliance with the License. 62d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * You may obtain a copy of the License at 72d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * 82d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * http://www.apache.org/licenses/LICENSE-2.0 92d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * 102d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * Unless required by applicable law or agreed to in writing, software 112d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * distributed under the License is distributed on an "AS IS" BASIS, 122d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * See the License for the specific language governing permissions and 142d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * limitations under the License. 152d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet */ 162d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet 172d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohetpackage android.graphics; 182d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet 19918aaa5717fce6081557c82ce1c439b6922737d5Xavier Ducrohetimport com.android.ide.common.rendering.api.LayoutLog; 20168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohetimport com.android.layoutlib.bridge.Bridge; 212d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohetimport com.android.layoutlib.bridge.impl.DelegateManager; 22d38e776a3cc8cb53945cbebafbe6f6c2e3501fa5Xavier Ducrohetimport com.android.layoutlib.bridge.impl.GcSnapshot; 232d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohetimport com.android.ninepatch.NinePatchChunk; 249a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohetimport com.android.tools.layoutlib.annotations.LayoutlibDelegate; 252d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet 262d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohetimport android.graphics.drawable.NinePatchDrawable; 272d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet 282d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohetimport java.awt.Graphics2D; 292d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohetimport java.awt.image.BufferedImage; 302d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohetimport java.io.ByteArrayInputStream; 312d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohetimport java.io.ByteArrayOutputStream; 322d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohetimport java.io.IOException; 332d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohetimport java.io.ObjectInputStream; 342d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohetimport java.io.ObjectOutputStream; 352d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohetimport java.lang.ref.SoftReference; 362d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohetimport java.util.HashMap; 372d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohetimport java.util.Map; 382d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet 392d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet/** 402d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * Delegate implementing the native methods of android.graphics.NinePatch 412d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * 422d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * Through the layoutlib_create tool, the original native methods of NinePatch have been replaced 432d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * by calls to methods of the same name in this delegate class. 442d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * 452d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * Because it's a stateless class to start with, there's no need to keep a {@link DelegateManager} 462d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * around to map int to instance of the delegate. 472d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * 482d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet */ 49d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohetpublic final class NinePatch_Delegate { 502d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet 512d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet /** 522d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * Cache map for {@link NinePatchChunk}. 532d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * When the chunks are created they are serialized into a byte[], and both are put 542d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * in the cache, using a {@link SoftReference} for the chunk. The default Java classes 552d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * for {@link NinePatch} and {@link NinePatchDrawable} only reference to the byte[] data, and 562d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * provide this for drawing. 572d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * Using the cache map allows us to not have to deserialize the byte[] back into a 582d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * {@link NinePatchChunk} every time a rendering is done. 592d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet */ 602d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet private final static Map<byte[], SoftReference<NinePatchChunk>> sChunkCache = 612d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet new HashMap<byte[], SoftReference<NinePatchChunk>>(); 622d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet 632d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet // ---- Public Helper methods ---- 642d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet 652d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet /** 662d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * Serializes the given chunk. 672d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * 682d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * @return the serialized data for the chunk. 692d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet */ 702d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet public static byte[] serialize(NinePatchChunk chunk) { 712d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet // serialize the chunk to get a byte[] 722d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet ByteArrayOutputStream baos = new ByteArrayOutputStream(); 732d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet ObjectOutputStream oos = null; 742d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet try { 752d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet oos = new ObjectOutputStream(baos); 762d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet oos.writeObject(chunk); 772d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet } catch (IOException e) { 7851a7e5447de94791c464cda5cc6ebbf616d73c80Xavier Ducrohet Bridge.getLog().error(null, "Failed to serialize NinePatchChunk.", e, null /*data*/); 792d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet return null; 802d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet } finally { 812d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet if (oos != null) { 822d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet try { 832d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet oos.close(); 842d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet } catch (IOException e) { 852d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet } 862d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet } 872d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet } 882d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet 892d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet // get the array and add it to the cache 902d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet byte[] array = baos.toByteArray(); 912d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet sChunkCache.put(array, new SoftReference<NinePatchChunk>(chunk)); 922d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet return array; 932d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet } 942d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet 9513bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet /** 9613bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet * Returns a {@link NinePatchChunk} object for the given serialized representation. 9713bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet * 9813bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet * If the chunk is present in the cache then the object from the cache is returned, otherwise 9913bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet * the array is deserialized into a {@link NinePatchChunk} object. 10013bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet * 10113bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet * @param array the serialized representation of the chunk. 10213bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet * @return the NinePatchChunk or null if deserialization failed. 10313bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet */ 10413bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet public static NinePatchChunk getChunk(byte[] array) { 10513bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet SoftReference<NinePatchChunk> chunkRef = sChunkCache.get(array); 10613bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet NinePatchChunk chunk = chunkRef.get(); 10713bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet if (chunk == null) { 10813bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet ByteArrayInputStream bais = new ByteArrayInputStream(array); 10913bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet ObjectInputStream ois = null; 11013bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet try { 11113bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet ois = new ObjectInputStream(bais); 11213bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet chunk = (NinePatchChunk) ois.readObject(); 11313bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet 11413bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet // put back the chunk in the cache 11513bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet if (chunk != null) { 11613bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet sChunkCache.put(array, new SoftReference<NinePatchChunk>(chunk)); 11713bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet } 11813bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet } catch (IOException e) { 11913bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet Bridge.getLog().error(LayoutLog.TAG_BROKEN, 12013bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet "Failed to deserialize NinePatchChunk content.", e, null /*data*/); 12113bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet return null; 12213bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet } catch (ClassNotFoundException e) { 12313bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet Bridge.getLog().error(LayoutLog.TAG_BROKEN, 12413bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet "Failed to deserialize NinePatchChunk class.", e, null /*data*/); 12513bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet return null; 12613bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet } finally { 12713bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet if (ois != null) { 12813bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet try { 12913bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet ois.close(); 13013bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet } catch (IOException e) { 13113bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet } 13213bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet } 13313bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet } 13413bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet } 13513bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet 13613bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet return chunk; 13713bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet } 13813bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet 1392d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet // ---- native methods ---- 1402d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet 1419a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet @LayoutlibDelegate 1422d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet /*package*/ static boolean isNinePatchChunk(byte[] chunk) { 1432d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet NinePatchChunk chunkObject = getChunk(chunk); 1442d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet if (chunkObject != null) { 1452d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet return true; 1462d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet } 1472d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet 1482d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet return false; 1492d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet } 1502d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet 1519a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet @LayoutlibDelegate 1522d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet /*package*/ static void validateNinePatchChunk(int bitmap, byte[] chunk) { 1532d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet // the default JNI implementation only checks that the byte[] has the same 1542d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet // size as the C struct it represent. Since we cannot do the same check (serialization 1552d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet // will return different size depending on content), we do nothing. 1562d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet } 1572d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet 1589a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet @LayoutlibDelegate 1592d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet /*package*/ static void nativeDraw(int canvas_instance, RectF loc, int bitmap_instance, 1602d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet byte[] c, int paint_instance_or_null, int destDensity, int srcDensity) { 1612d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet draw(canvas_instance, 1622d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet (int) loc.left, (int) loc.top, (int) loc.width(), (int) loc.height(), 1632d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet bitmap_instance, c, paint_instance_or_null, 1642d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet destDensity, srcDensity); 1652d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet } 1662d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet 1679a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet @LayoutlibDelegate 1682d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet /*package*/ static void nativeDraw(int canvas_instance, Rect loc, int bitmap_instance, 1692d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet byte[] c, int paint_instance_or_null, int destDensity, int srcDensity) { 1702d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet draw(canvas_instance, 1712d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet loc.left, loc.top, loc.width(), loc.height(), 1722d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet bitmap_instance, c, paint_instance_or_null, 1732d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet destDensity, srcDensity); 1742d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet } 1752d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet 1769a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet @LayoutlibDelegate 1772d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet /*package*/ static int nativeGetTransparentRegion(int bitmap, byte[] chunk, Rect location) { 1782d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet return 0; 1792d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet } 1802d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet 1812d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet // ---- Private Helper methods ---- 1822d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet 1839a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet private static void draw(int canvas_instance, 1849a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet final int left, final int top, final int right, final int bottom, 1859a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet int bitmap_instance, byte[] c, int paint_instance_or_null, 1869a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet final int destDensity, final int srcDensity) { 1879a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet // get the delegate from the native int. 1889a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet final Bitmap_Delegate bitmap_delegate = Bitmap_Delegate.getDelegate(bitmap_instance); 1899a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet if (bitmap_delegate == null) { 1909a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet return; 1919a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet } 1929a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet 1939a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet if (c == null) { 1949a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet // not a 9-patch? 1959a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet BufferedImage image = bitmap_delegate.getImage(); 1969a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet Canvas_Delegate.native_drawBitmap(canvas_instance, bitmap_instance, 1979a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet new Rect(0, 0, image.getWidth(), image.getHeight()), 1989a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet new Rect(left, top, right, bottom), 1999a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet paint_instance_or_null, destDensity, srcDensity); 2009a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet return; 2019a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet } 2029a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet 2039a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet final NinePatchChunk chunkObject = getChunk(c); 2049a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet assert chunkObject != null; 2059a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet if (chunkObject == null) { 2069a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet return; 2079a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet } 2089a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet 2099a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet Canvas_Delegate canvas_delegate = Canvas_Delegate.getDelegate(canvas_instance); 2109a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet if (canvas_delegate == null) { 2119a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet return; 2129a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet } 2139a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet 2149a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet // this one can be null 2159a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet Paint_Delegate paint_delegate = Paint_Delegate.getDelegate(paint_instance_or_null); 2169a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet 2179a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet canvas_delegate.getSnapshot().draw(new GcSnapshot.Drawable() { 21846d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet @Override 2199a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet public void draw(Graphics2D graphics, Paint_Delegate paint) { 2209a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet chunkObject.draw(bitmap_delegate.getImage(), graphics, 2219a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet left, top, right - left, bottom - top, destDensity, srcDensity); 2229a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet } 2239a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet }, paint_delegate, true /*compositeOnly*/, false /*forceSrcMode*/); 2242d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet 2259a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet } 2262d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet} 227