1fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet/* 2fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet * Copyright (C) 2011 The Android Open Source Project 3fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet * 4fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet * Licensed under the Apache License, Version 2.0 (the "License"); 5fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet * you may not use this file except in compliance with the License. 6fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet * You may obtain a copy of the License at 7fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet * 8fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet * http://www.apache.org/licenses/LICENSE-2.0 9fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet * 10fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet * Unless required by applicable law or agreed to in writing, software 11fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet * distributed under the License is distributed on an "AS IS" BASIS, 12fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet * See the License for the specific language governing permissions and 14fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet * limitations under the License. 15fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet */ 16fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet 17fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetpackage com.android.layoutlib.bridge.impl; 18fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet 19fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN; 20fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet 21fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport com.android.ide.common.rendering.api.DrawableParams; 22891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohetimport com.android.ide.common.rendering.api.HardwareConfig; 23fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport com.android.ide.common.rendering.api.ResourceValue; 24fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport com.android.ide.common.rendering.api.Result; 25fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport com.android.ide.common.rendering.api.Result.Status; 26fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeContext; 27fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport com.android.resources.ResourceType; 28fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet 29fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport android.graphics.Bitmap; 30fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport android.graphics.Bitmap_Delegate; 31fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport android.graphics.Canvas; 32fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport android.graphics.drawable.Drawable; 337f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohetimport android.view.AttachInfo_Accessor; 34fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport android.view.View.MeasureSpec; 35fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport android.widget.FrameLayout; 36fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet 37fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport java.awt.AlphaComposite; 38fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport java.awt.Color; 39fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport java.awt.Graphics2D; 40fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport java.awt.image.BufferedImage; 41fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport java.io.IOException; 42fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet 43fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet/** 44fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet * Action to render a given Drawable provided through {@link DrawableParams#getDrawable()}. 45fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet * 46fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet * The class only provides a simple {@link #render()} method, but the full life-cycle of the 47fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet * action must be respected. 48fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet * 49fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet * @see RenderAction 50fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet * 51fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet */ 52fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetpublic class RenderDrawable extends RenderAction<DrawableParams> { 53fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet 54fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet public RenderDrawable(DrawableParams params) { 55fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet super(new DrawableParams(params)); 56fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet } 57fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet 58fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet public Result render() { 59fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet checkLock(); 60fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet try { 61fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet // get the drawable resource value 62fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet DrawableParams params = getParams(); 63891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet HardwareConfig hardwareConfig = params.getHardwareConfig(); 64fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet ResourceValue drawableResource = params.getDrawable(); 65fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet 66fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet // resolve it 67fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet BridgeContext context = getContext(); 68fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet drawableResource = context.getRenderResources().resolveResValue(drawableResource); 69fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet 70fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet if (drawableResource == null || 71fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet drawableResource.getResourceType() != ResourceType.DRAWABLE) { 72fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet return Status.ERROR_NOT_A_DRAWABLE.createResult(); 73fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet } 74fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet 75fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet // create a simple FrameLayout 76fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet FrameLayout content = new FrameLayout(context); 77fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet 78fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet // get the actual Drawable object to draw 79fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet Drawable d = ResourceHelper.getDrawable(drawableResource, context); 80891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet content.setBackground(d); 81fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet 82fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet // set the AttachInfo on the root view. 837f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohet AttachInfo_Accessor.setAttachInfo(content); 84fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet 85fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet 86fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet // measure 87891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet int w = hardwareConfig.getScreenWidth(); 88891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet int h = hardwareConfig.getScreenHeight(); 89fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet int w_spec = MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY); 90fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet int h_spec = MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY); 91fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet content.measure(w_spec, h_spec); 92fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet 93fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet // now do the layout. 94fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet content.layout(0, 0, w, h); 95fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet 96fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet // preDraw setup 977f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohet AttachInfo_Accessor.dispatchOnPreDraw(content); 98fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet 99fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet // draw into a new image 100fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet BufferedImage image = getImage(w, h); 101fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet 102fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet // create an Android bitmap around the BufferedImage 103fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet Bitmap bitmap = Bitmap_Delegate.createBitmap(image, 104891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet true /*isMutable*/, hardwareConfig.getDensity()); 105fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet 106fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet // create a Canvas around the Android bitmap 107fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet Canvas canvas = new Canvas(bitmap); 108891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet canvas.setDensity(hardwareConfig.getDensity().getDpiValue()); 109fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet 110fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet // and draw 111fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet content.draw(canvas); 112fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet 113fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet return Status.SUCCESS.createResult(image); 114fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet } catch (IOException e) { 115fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet return ERROR_UNKNOWN.createResult(e.getMessage(), e); 116fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet } 117fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet } 118fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet 119fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet protected BufferedImage getImage(int w, int h) { 120fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); 121fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet Graphics2D gc = image.createGraphics(); 122fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet gc.setComposite(AlphaComposite.Src); 123fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet 124fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet gc.setColor(new Color(0x00000000, true)); 125fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet gc.fillRect(0, 0, w, h); 126fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet 127fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet // done 128fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet gc.dispose(); 129fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet 130fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet return image; 131fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet } 132fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet 133fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet} 134