1 /*
2  * Copyright (C) 2023 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 package com.android.internal.widget.remotecompose.player.platform;
17 
18 import android.graphics.Bitmap;
19 import android.graphics.BitmapFactory;
20 import android.graphics.Canvas;
21 
22 import com.android.internal.widget.remotecompose.core.RemoteContext;
23 import com.android.internal.widget.remotecompose.core.VariableSupport;
24 import com.android.internal.widget.remotecompose.core.operations.FloatExpression;
25 import com.android.internal.widget.remotecompose.core.operations.ShaderData;
26 
27 import java.util.HashMap;
28 
29 /**
30  * An implementation of Context for Android.
31  * <p>
32  * This is used to play the RemoteCompose operations on Android.
33  */
34 class AndroidRemoteContext extends RemoteContext {
35 
useCanvas(Canvas canvas)36     public void useCanvas(Canvas canvas) {
37         if (mPaintContext == null) {
38             mPaintContext = new AndroidPaintContext(this, canvas);
39         } else {
40             // need to make sure to update the canvas for the current one
41             mPaintContext.reset();
42             ((AndroidPaintContext) mPaintContext).setCanvas(canvas);
43         }
44         mWidth = canvas.getWidth();
45         mHeight = canvas.getHeight();
46     }
47 
48     ///////////////////////////////////////////////////////////////////////////////////////////////
49     // Data handling
50     ///////////////////////////////////////////////////////////////////////////////////////////////
51 
52     @Override
loadPathData(int instanceId, float[] floatPath)53     public void loadPathData(int instanceId, float[] floatPath) {
54         if (!mRemoteComposeState.containsId(instanceId)) {
55             mRemoteComposeState.cache(instanceId, floatPath);
56         }
57     }
58 
59     static class VarName {
60         String mName;
61         int mId;
62         int mType;
63 
VarName(String name, int id, int type)64         VarName(String name, int id, int type) {
65             mName = name;
66             mId = id;
67             mType = type;
68         }
69     }
70 
71     HashMap<String, VarName> mVarNameHashMap = new HashMap<>();
72 
73     @Override
loadVariableName(String varName, int varId, int varType)74     public void loadVariableName(String varName, int varId, int varType) {
75         mVarNameHashMap.put(varName, new VarName(varName, varId, varType));
76     }
77 
78     /**
79      * Decode a byte array into an image and cache it using the given imageId
80      *
81      * @param width  with of image to be loaded
82      * @param height height of image to be loaded
83      * @param bitmap a byte array containing the image information
84      * @oaram imageId the id of the image
85      */
86     @Override
loadBitmap(int imageId, int width, int height, byte[] bitmap)87     public void loadBitmap(int imageId, int width, int height, byte[] bitmap) {
88         if (!mRemoteComposeState.containsId(imageId)) {
89             Bitmap image = BitmapFactory.decodeByteArray(bitmap, 0, bitmap.length);
90             mRemoteComposeState.cache(imageId, image);
91         }
92     }
93 
94     @Override
loadText(int id, String text)95     public void loadText(int id, String text) {
96         if (!mRemoteComposeState.containsId(id)) {
97             mRemoteComposeState.cache(id, text);
98         } else {
99             mRemoteComposeState.update(id, text);
100         }
101     }
102 
103     @Override
getText(int id)104     public String getText(int id) {
105         return (String) mRemoteComposeState.getFromId(id);
106     }
107 
108     @Override
loadFloat(int id, float value)109     public void loadFloat(int id, float value) {
110         mRemoteComposeState.updateFloat(id, value);
111     }
112 
113 
114     @Override
loadColor(int id, int color)115     public void loadColor(int id, int color) {
116         mRemoteComposeState.updateColor(id, color);
117     }
118 
119     @Override
loadAnimatedFloat(int id, FloatExpression animatedFloat)120     public void loadAnimatedFloat(int id, FloatExpression animatedFloat) {
121         mRemoteComposeState.cache(id, animatedFloat);
122     }
123 
124     @Override
loadShader(int id, ShaderData value)125     public void loadShader(int id, ShaderData value) {
126         mRemoteComposeState.cache(id, value);
127     }
128 
129     @Override
getFloat(int id)130     public float getFloat(int id) {
131         return (float) mRemoteComposeState.getFloat(id);
132     }
133 
134     @Override
getColor(int id)135     public int getColor(int id) {
136         return mRemoteComposeState.getColor(id);
137     }
138 
139     @Override
listensTo(int id, VariableSupport variableSupport)140     public void listensTo(int id, VariableSupport variableSupport) {
141         mRemoteComposeState.listenToVar(id, variableSupport);
142     }
143 
144     @Override
updateOps()145     public int updateOps() {
146         return mRemoteComposeState.getOpsToUpdate(this);
147     }
148 
149     @Override
getShader(int id)150     public ShaderData getShader(int id) {
151         return (ShaderData) mRemoteComposeState.getFromId(id);
152     }
153 
154     ///////////////////////////////////////////////////////////////////////////////////////////////
155     // Click handling
156     ///////////////////////////////////////////////////////////////////////////////////////////////
157 
158     @Override
addClickArea(int id, int contentDescriptionId, float left, float top, float right, float bottom, int metadataId)159     public void addClickArea(int id,
160                              int contentDescriptionId,
161                              float left,
162                              float top,
163                              float right,
164                              float bottom,
165                              int metadataId) {
166         String contentDescription = (String) mRemoteComposeState.getFromId(contentDescriptionId);
167         String metadata = (String) mRemoteComposeState.getFromId(metadataId);
168         mDocument.addClickArea(id, contentDescription, left, top, right, bottom, metadata);
169     }
170 }
171 
172