1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Copyright (C) 2011 The Android Open Source Project 3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * you may not use this file except in compliance with the License. 6282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * You may obtain a copy of the License at 7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 9282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Unless required by applicable law or agreed to in writing, software 11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * See the License for the specific language governing permissions and 14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * limitations under the License. 15282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipackage com.android.layoutlib.bridge.impl; 18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN; 20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.ide.common.rendering.api.DrawableParams; 22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.ide.common.rendering.api.HardwareConfig; 23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.ide.common.rendering.api.ResourceValue; 24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.ide.common.rendering.api.Result; 25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.ide.common.rendering.api.Result.Status; 26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.layoutlib.bridge.android.BridgeContext; 27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.resources.ResourceType; 28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.graphics.Bitmap; 30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.graphics.Bitmap_Delegate; 31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.graphics.Canvas; 32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.graphics.drawable.Drawable; 33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.view.AttachInfo_Accessor; 34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.view.View.MeasureSpec; 35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.widget.FrameLayout; 36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.awt.AlphaComposite; 38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.awt.Color; 39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.awt.Graphics2D; 40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.awt.image.BufferedImage; 41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.io.IOException; 42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/** 44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Action to render a given Drawable provided through {@link DrawableParams#getDrawable()}. 45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * The class only provides a simple {@link #render()} method, but the full life-cycle of the 47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * action must be respected. 48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @see RenderAction 50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipublic class RenderDrawable extends RenderAction<DrawableParams> { 53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public RenderDrawable(DrawableParams params) { 55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski super(new DrawableParams(params)); 56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public Result render() { 59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski checkLock(); 60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski try { 61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // get the drawable resource value 62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski DrawableParams params = getParams(); 63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski HardwareConfig hardwareConfig = params.getHardwareConfig(); 64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResourceValue drawableResource = params.getDrawable(); 65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // resolve it 67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski BridgeContext context = getContext(); 68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski drawableResource = context.getRenderResources().resolveResValue(drawableResource); 69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (drawableResource == null || 71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski drawableResource.getResourceType() != ResourceType.DRAWABLE) { 72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return Status.ERROR_NOT_A_DRAWABLE.createResult(); 73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // create a simple FrameLayout 76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski FrameLayout content = new FrameLayout(context); 77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // get the actual Drawable object to draw 79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Drawable d = ResourceHelper.getDrawable(drawableResource, context); 80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski content.setBackground(d); 81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // set the AttachInfo on the root view. 83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski AttachInfo_Accessor.setAttachInfo(content); 84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // measure 87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int w = hardwareConfig.getScreenWidth(); 88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int h = hardwareConfig.getScreenHeight(); 89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int w_spec = MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY); 90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int h_spec = MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY); 91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski content.measure(w_spec, h_spec); 92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // now do the layout. 94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski content.layout(0, 0, w, h); 95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // preDraw setup 97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski AttachInfo_Accessor.dispatchOnPreDraw(content); 98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // draw into a new image 100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski BufferedImage image = getImage(w, h); 101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // create an Android bitmap around the BufferedImage 103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Bitmap bitmap = Bitmap_Delegate.createBitmap(image, 104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski true /*isMutable*/, hardwareConfig.getDensity()); 105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // create a Canvas around the Android bitmap 107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Canvas canvas = new Canvas(bitmap); 108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski canvas.setDensity(hardwareConfig.getDensity().getDpiValue()); 109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // and draw 111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski content.draw(canvas); 112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return Status.SUCCESS.createResult(image); 114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } catch (IOException e) { 115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return ERROR_UNKNOWN.createResult(e.getMessage(), e); 116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski protected BufferedImage getImage(int w, int h) { 120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); 121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Graphics2D gc = image.createGraphics(); 122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski gc.setComposite(AlphaComposite.Src); 123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski gc.setColor(new Color(0x00000000, true)); 125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski gc.fillRect(0, 0, w, h); 126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // done 128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski gc.dispose(); 129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return image; 131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 134