RenderDrawable.java revision fd18f573280bbbcc549b35b548580a562bd960e2
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;
22fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport com.android.ide.common.rendering.api.ResourceValue;
23fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport com.android.ide.common.rendering.api.Result;
24fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport com.android.ide.common.rendering.api.Result.Status;
25fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeContext;
26fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeWindow;
27fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeWindowSession;
28fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport com.android.resources.ResourceType;
29fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet
30fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport android.graphics.Bitmap;
31fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport android.graphics.Bitmap_Delegate;
32fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport android.graphics.Canvas;
33fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport android.graphics.drawable.Drawable;
34fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport android.os.Handler;
35fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport android.view.View;
36fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport android.view.View.AttachInfo;
37fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport android.view.View.MeasureSpec;
38fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport android.widget.FrameLayout;
39fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet
40fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport java.awt.AlphaComposite;
41fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport java.awt.Color;
42fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport java.awt.Graphics2D;
43fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport java.awt.image.BufferedImage;
44fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport java.io.IOException;
45fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet
46fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet/**
47fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet * Action to render a given Drawable provided through {@link DrawableParams#getDrawable()}.
48fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet *
49fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet * The class only provides a simple {@link #render()} method, but the full life-cycle of the
50fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet * action must be respected.
51fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet *
52fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet * @see RenderAction
53fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet *
54fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet */
55fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetpublic class RenderDrawable extends RenderAction<DrawableParams> {
56fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet
57fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet    public RenderDrawable(DrawableParams params) {
58fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet        super(new DrawableParams(params));
59fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet    }
60fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet
61fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet    public Result render() {
62fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet        checkLock();
63fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet        try {
64fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            // get the drawable resource value
65fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            DrawableParams params = getParams();
66fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            ResourceValue drawableResource = params.getDrawable();
67fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet
68fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            // resolve it
69fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            BridgeContext context = getContext();
70fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            drawableResource = context.getRenderResources().resolveResValue(drawableResource);
71fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet
72fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            if (drawableResource == null ||
73fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet                    drawableResource.getResourceType() != ResourceType.DRAWABLE) {
74fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet                return Status.ERROR_NOT_A_DRAWABLE.createResult();
75fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            }
76fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet
77fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            // create a simple FrameLayout
78fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            FrameLayout content = new FrameLayout(context);
79fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet
80fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            // get the actual Drawable object to draw
81fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            Drawable d = ResourceHelper.getDrawable(drawableResource, context);
82fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            content.setBackgroundDrawable(d);
83fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet
84fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            // set the AttachInfo on the root view.
85fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            AttachInfo info = new AttachInfo(new BridgeWindowSession(), new BridgeWindow(),
86fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet                    new Handler(), null);
87fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            info.mHasWindowFocus = true;
88fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            info.mWindowVisibility = View.VISIBLE;
89fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            info.mInTouchMode = false; // this is so that we can display selections.
90fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            info.mHardwareAccelerated = false;
91fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            content.dispatchAttachedToWindow(info, 0);
92fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet
93fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet
94fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            // measure
95fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            int w = params.getScreenWidth();
96fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            int h = params.getScreenHeight();
97fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            int w_spec = MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY);
98fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            int h_spec = MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY);
99fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            content.measure(w_spec, h_spec);
100fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet
101fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            // now do the layout.
102fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            content.layout(0, 0, w, h);
103fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet
104fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            // preDraw setup
105fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            content.mAttachInfo.mTreeObserver.dispatchOnPreDraw();
106fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet
107fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            // draw into a new image
108fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            BufferedImage image = getImage(w, h);
109fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet
110fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            // create an Android bitmap around the BufferedImage
111fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            Bitmap bitmap = Bitmap_Delegate.createBitmap(image,
112fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet                    true /*isMutable*/, params.getDensity());
113fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet
114fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            // create a Canvas around the Android bitmap
115fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            Canvas canvas = new Canvas(bitmap);
116fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            canvas.setDensity(params.getDensity().getDpiValue());
117fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet
118fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            // and draw
119fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            content.draw(canvas);
120fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet
121fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            return Status.SUCCESS.createResult(image);
122fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet        } catch (IOException e) {
123fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet            return ERROR_UNKNOWN.createResult(e.getMessage(), e);
124fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet        }
125fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet    }
126fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet
127fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet    protected BufferedImage getImage(int w, int h) {
128fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet        BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
129fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet        Graphics2D gc = image.createGraphics();
130fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet        gc.setComposite(AlphaComposite.Src);
131fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet
132fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet        gc.setColor(new Color(0x00000000, true));
133fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet        gc.fillRect(0, 0, w, h);
134fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet
135fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet        // done
136fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet        gc.dispose();
137fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet
138fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet        return image;
139fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet    }
140fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet
141fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet}
142