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