1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.view.shadow;
18 
19 import com.android.ide.common.rendering.api.LayoutLog;
20 import com.android.layoutlib.bridge.Bridge;
21 
22 import android.graphics.Bitmap;
23 import android.view.math.Math3DHelper;
24 
25 /**
26  * Generates ambient shadow bitmap
27  */
28 class AmbientShadowBitmapGenerator {
29 
30     private final AmbientShadowConfig mShadowConfig;
31     private final TriangleBuffer mTriangleBuffer;
32     private final AmbientShadowVertexCalculator mCalculator;
33 
34     private float mTranslateX;
35     private float mTranslateY;
36 
37     private boolean mValid;
38 
AmbientShadowBitmapGenerator(AmbientShadowConfig shadowConfig)39     public AmbientShadowBitmapGenerator(AmbientShadowConfig shadowConfig) {
40         mShadowConfig = shadowConfig;
41 
42         mTriangleBuffer = new TriangleBuffer();
43         mTriangleBuffer.setSize(mShadowConfig.getWidth(), mShadowConfig.getHeight(), 0);
44 
45         mCalculator = new AmbientShadowVertexCalculator(mShadowConfig);
46     }
47 
48     /**
49      * Populate vertices and fill the triangle buffers. To be called before {@link #getBitmap()}
50      */
populateShadow()51     public void populateShadow() {
52         try {
53             mValid = mCalculator.generateVertex(mShadowConfig.getPolygon());
54             if (!mValid) {
55                 Bridge.getLog().warning(LayoutLog.TAG_INFO,  "Arithmetic error while " +
56                                 "drawing ambient shadow", null, null);
57                 return;
58             }
59 
60             float[] shadowBounds = Math3DHelper.flatBound(mCalculator.getVertex(), 2);
61             if (shadowBounds[0] < 0) {
62                 // translate to right by the offset amount.
63                 mTranslateX = shadowBounds[0] * -1;
64             } else if (shadowBounds[2] > mShadowConfig.getWidth()) {
65                 // translate to left by the offset amount.
66                 mTranslateX = shadowBounds[2] - mShadowConfig.getWidth();
67             }
68 
69             if (shadowBounds[1] < 0) {
70                 mTranslateY = shadowBounds[1] * -1;
71             } else if (shadowBounds[3] > mShadowConfig.getHeight()) {
72                 mTranslateY = shadowBounds[3] - mShadowConfig.getHeight();
73             }
74 
75             Math3DHelper.translate(mCalculator.getVertex(), mTranslateX, mTranslateY, 2);
76 
77             mTriangleBuffer.drawTriangles(mCalculator.getIndex(), mCalculator.getVertex(),
78                     mCalculator.getColor(), mShadowConfig.getShadowStrength());
79         } catch (IndexOutOfBoundsException|ArithmeticException mathError) {
80             Bridge.getLog().warning(LayoutLog.TAG_INFO,  "Arithmetic error while drawing " +
81                             "ambient shadow",
82                     mathError);
83         } catch (Exception ex) {
84             Bridge.getLog().warning(LayoutLog.TAG_INFO,  "Error while drawing shadow",
85                     ex);
86         }
87     }
88 
isValid()89     public boolean isValid() {
90         return mValid;
91     }
92 
getBitmap()93     public Bitmap getBitmap() {
94         return mTriangleBuffer.getImage();
95     }
96 
getTranslateX()97     public float getTranslateX() {
98         return mTranslateX;
99     }
100 
getTranslateY()101     public float getTranslateY() {
102         return mTranslateY;
103     }
104 }
105