• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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.core.operations.layout.modifiers;
17 
18 import android.annotation.NonNull;
19 import android.annotation.Nullable;
20 
21 import com.android.internal.widget.remotecompose.core.Operation;
22 import com.android.internal.widget.remotecompose.core.Operations;
23 import com.android.internal.widget.remotecompose.core.PaintContext;
24 import com.android.internal.widget.remotecompose.core.RemoteContext;
25 import com.android.internal.widget.remotecompose.core.WireBuffer;
26 import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
27 import com.android.internal.widget.remotecompose.core.operations.layout.AnimatableValue;
28 import com.android.internal.widget.remotecompose.core.operations.layout.Component;
29 import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer;
30 import com.android.internal.widget.remotecompose.core.serialize.MapSerializer;
31 import com.android.internal.widget.remotecompose.core.serialize.SerializeTags;
32 
33 import java.util.HashMap;
34 import java.util.List;
35 
36 /** Represents a graphics layer modifier. */
37 public class GraphicsLayerModifierOperation extends DecoratorModifierOperation {
38     private static final int OP_CODE = Operations.MODIFIER_GRAPHICS_LAYER;
39     public static final String CLASS_NAME = "GraphicsLayerModifierOperation";
40 
41     public static final int SCALE_X = 0;
42     public static final int SCALE_Y = 1;
43     public static final int ROTATION_X = 2;
44     public static final int ROTATION_Y = 3;
45     public static final int ROTATION_Z = 4;
46     public static final int TRANSFORM_ORIGIN_X = 5;
47     public static final int TRANSFORM_ORIGIN_Y = 6;
48     public static final int TRANSLATION_X = 7;
49     public static final int TRANSLATION_Y = 8;
50     public static final int TRANSLATION_Z = 9;
51     public static final int SHADOW_ELEVATION = 10;
52     public static final int ALPHA = 11;
53     public static final int CAMERA_DISTANCE = 12;
54     public static final int COMPOSITING_STRATEGY = 13;
55     public static final int SPOT_SHADOW_COLOR = 14;
56     public static final int AMBIENT_SHADOW_COLOR = 15;
57     public static final int HAS_BLUR = 16;
58     public static final int BLUR_RADIUS_X = 17;
59     public static final int BLUR_RADIUS_Y = 18;
60     public static final int BLUR_TILE_MODE = 19;
61     public static final int SHAPE = 20;
62     public static final int SHAPE_RADIUS = 21;
63 
64     public static final int SHAPE_RECT = 0;
65     public static final int SHAPE_ROUND_RECT = 1;
66     public static final int SHAPE_CIRCLE = 2;
67 
68     public static final int TILE_MODE_CLAMP = 0;
69     public static final int TILE_MODE_REPEATED = 1;
70     public static final int TILE_MODE_MIRROR = 2;
71     public static final int TILE_MODE_DECAL = 3;
72 
73     /** The object is an integer */
74     private static final short DATA_TYPE_INT = 0;
75 
76     /** The object is an float */
77     private static final short DATA_TYPE_FLOAT = 1;
78 
79     AttributeValue[] mValues = {
80         new AttributeValue(SCALE_X, "SCALE_X", 1f),
81         new AttributeValue(SCALE_Y, "SCALE_Y", 1f),
82         new AttributeValue(ROTATION_X, "ROTATION_X", 0f),
83         new AttributeValue(ROTATION_Y, "ROTATION_Y", 0f),
84         new AttributeValue(ROTATION_Z, "ROTATION_Z", 0f),
85         new AttributeValue(TRANSFORM_ORIGIN_X, "TRANSFORM_ORIGIN_X", 0f),
86         new AttributeValue(TRANSFORM_ORIGIN_Y, "TRANSFORM_ORIGIN_Y", 0f),
87         new AttributeValue(TRANSLATION_X, "TRANSLATION_X", 0f),
88         new AttributeValue(TRANSLATION_Y, "TRANSLATION_Y", 0f),
89         new AttributeValue(TRANSLATION_Z, "TRANSLATION_Z", 0f),
90         new AttributeValue(SHADOW_ELEVATION, "SHADOW_ELEVATION", 0f),
91         new AttributeValue(ALPHA, "ALPHA", 1f),
92         new AttributeValue(CAMERA_DISTANCE, "CAMERA_DISTANCE", 8f),
93         new AttributeValue(COMPOSITING_STRATEGY, "COMPOSITING_STRATEGY", 0),
94         new AttributeValue(SPOT_SHADOW_COLOR, "SPOT_SHADOW_COLOR", 0),
95         new AttributeValue(AMBIENT_SHADOW_COLOR, "AMBIENT_SHADOW_COLOR", 0),
96         new AttributeValue(HAS_BLUR, "HAS_BLUR", 0),
97         new AttributeValue(BLUR_RADIUS_X, "BLUR_RADIUS_X", 0f),
98         new AttributeValue(BLUR_RADIUS_Y, "BLUR_RADIUS_Y", 0f),
99         new AttributeValue(BLUR_TILE_MODE, "BLUR_TILE_MODE", TILE_MODE_CLAMP),
100         new AttributeValue(SHAPE, "SHAPE", -1),
101         new AttributeValue(SHAPE_RADIUS, "SHAPE_RADIUS", 0f),
102     };
103 
104     boolean mHasBlurEffect = false;
105 
106     /**
107      * Fill in the hashmap with the attributes values
108      *
109      * @param attributes
110      */
fillInAttributes(HashMap<Integer, Object> attributes)111     public void fillInAttributes(HashMap<Integer, Object> attributes) {
112         for (int i = 0; i < mValues.length; i++) {
113             if (mValues[i].needsToWrite()) {
114                 attributes.put(i, mValues[i].getObjectValue());
115             }
116         }
117     }
118 
119     static final int FLOAT_VALUE = 0;
120     static final int INT_VALUE = 1;
121 
122     /** Utility class to manage attributes */
123     static class AttributeValue {
124         String mName;
125         int mId;
126         @Nullable AnimatableValue mAnimatableValue;
127         float mDefaultValue = 0f;
128         int mIntValue = 0;
129         int mIntDefaultValue = 0;
130         int mType = FLOAT_VALUE;
131 
AttributeValue(int id, String name, float defaultValue)132         AttributeValue(int id, String name, float defaultValue) {
133             mId = id;
134             mName = name;
135             mDefaultValue = defaultValue;
136             mType = FLOAT_VALUE;
137         }
138 
AttributeValue(int id, String name, int defaultValue)139         AttributeValue(int id, String name, int defaultValue) {
140             mId = id;
141             mName = name;
142             mIntDefaultValue = defaultValue;
143             mType = INT_VALUE;
144         }
145 
getValue()146         public float getValue() {
147             if (mType == FLOAT_VALUE) {
148                 if (mAnimatableValue != null) {
149                     return mAnimatableValue.getValue();
150                 }
151                 return mDefaultValue;
152             } else {
153                 return mIntValue;
154             }
155         }
156 
getIntValue()157         public int getIntValue() {
158             if (mType == FLOAT_VALUE) {
159                 if (mAnimatableValue != null) {
160                     return (int) mAnimatableValue.getValue();
161                 }
162             } else if (mType == INT_VALUE) {
163                 return mIntValue;
164             }
165             return 0;
166         }
167 
evaluate(PaintContext context)168         public void evaluate(PaintContext context) {
169             if (mAnimatableValue != null) {
170                 mAnimatableValue.evaluate(context);
171             }
172         }
173 
needsToWrite()174         public boolean needsToWrite() {
175             if (mType == FLOAT_VALUE) {
176                 if (mAnimatableValue != null) {
177                     return mAnimatableValue.getValue() != mDefaultValue;
178                 }
179                 return false;
180             } else if (mType == INT_VALUE) {
181                 return mIntValue != mIntDefaultValue;
182             }
183             return false;
184         }
185 
write(WireBuffer buffer)186         public void write(WireBuffer buffer) {
187             buffer.writeInt(mId);
188             if (mType == FLOAT_VALUE) {
189                 buffer.writeFloat(getValue());
190             } else if (mType == INT_VALUE) {
191                 buffer.writeInt(getIntValue());
192             }
193         }
194 
getObjectValue()195         public Object getObjectValue() {
196             if (mType == FLOAT_VALUE) {
197                 return getValue();
198             }
199             return getIntValue();
200         }
201 
setValue(float value)202         public void setValue(float value) {
203             mAnimatableValue = new AnimatableValue(value);
204         }
205 
setValue(int value)206         public void setValue(int value) {
207             mIntValue = value;
208         }
209     }
210 
211     @Override
write(@onNull WireBuffer buffer)212     public void write(@NonNull WireBuffer buffer) {
213         buffer.start(OP_CODE);
214         buffer.writeInt(mValues.length);
215         for (int i = 0; i < mValues.length; i++) {
216             AttributeValue value = mValues[i];
217             if (value.needsToWrite()) {
218                 value.write(buffer);
219             }
220         }
221     }
222 
223     @Override
serializeToString(int indent, StringSerializer serializer)224     public void serializeToString(int indent, StringSerializer serializer) {
225         serializer.append(
226                 indent,
227                 "GRAPHICS_LAYER = ["
228                         + mValues[SCALE_X].getValue()
229                         + ", "
230                         + mValues[SCALE_Y].getValue()
231                         + "]");
232     }
233 
234     @NonNull
235     @Override
deepToString(@onNull String indent)236     public String deepToString(@NonNull String indent) {
237         return indent + toString();
238     }
239 
240     @Override
paint(@onNull PaintContext context)241     public void paint(@NonNull PaintContext context) {
242         for (int i = 0; i < mValues.length; i++) {
243             AttributeValue v = mValues[i];
244             v.evaluate(context);
245         }
246     }
247 
248     @Override
toString()249     public String toString() {
250         return "GraphicsLayerModifierOperation("
251                 + mValues[SCALE_X].getValue()
252                 + ", "
253                 + mValues[SCALE_Y].getValue()
254                 + ")";
255     }
256 
257     /**
258      * The name of the class
259      *
260      * @return the name
261      */
262     @NonNull
name()263     public static String name() {
264         return CLASS_NAME;
265     }
266 
267     /**
268      * The OP_CODE for this command
269      *
270      * @return the opcode
271      */
id()272     public static int id() {
273         return OP_CODE;
274     }
275 
276     /**
277      * Write the operation to the buffer
278      *
279      * @param buffer a WireBuffer
280      * @param values attributes of the layer
281      */
apply(WireBuffer buffer, HashMap<Integer, Object> values)282     public static void apply(WireBuffer buffer, HashMap<Integer, Object> values) {
283         buffer.start(OP_CODE);
284         int size = values.size();
285         buffer.writeInt(size);
286         for (Integer key : values.keySet()) {
287             Object value = values.get(key);
288             if (value instanceof Integer) {
289                 writeIntAttribute(buffer, key, (Integer) value);
290             } else if (value instanceof Float) {
291                 writeFloatAttribute(buffer, key, (Float) value);
292             }
293         }
294     }
295 
296     /**
297      * Utility to write an integer attribute
298      *
299      * @param buffer
300      * @param type
301      * @param value
302      */
writeIntAttribute(WireBuffer buffer, int type, int value)303     private static void writeIntAttribute(WireBuffer buffer, int type, int value) {
304         int tag = type | (DATA_TYPE_INT << 10);
305         buffer.writeInt(tag);
306         buffer.writeInt(value);
307     }
308 
309     /**
310      * Utility to write a float attribute
311      *
312      * @param buffer
313      * @param type
314      * @param value
315      */
writeFloatAttribute(WireBuffer buffer, int type, float value)316     private static void writeFloatAttribute(WireBuffer buffer, int type, float value) {
317         int tag = type | (DATA_TYPE_FLOAT << 10);
318         buffer.writeInt(tag);
319         buffer.writeFloat(value);
320     }
321 
322     /**
323      * Read the operation from the buffer
324      *
325      * @param buffer a WireBuffer
326      * @param operations the list of operations read so far
327      */
read(WireBuffer buffer, List<Operation> operations)328     public static void read(WireBuffer buffer, List<Operation> operations) {
329         int length = buffer.readInt();
330         GraphicsLayerModifierOperation op = new GraphicsLayerModifierOperation();
331         for (int i = 0; i < length; i++) {
332             op.readAttributeValue(buffer);
333         }
334         operations.add(op);
335     }
336 
337     /**
338      * Read a single attribute value from the buffer
339      *
340      * @param buffer
341      */
readAttributeValue(WireBuffer buffer)342     private void readAttributeValue(WireBuffer buffer) {
343         int tag = buffer.readInt();
344         int dataType = tag >> 10;
345         int index = (short) (tag & 0x3F);
346         if (index == BLUR_RADIUS_X || index == BLUR_RADIUS_Y) {
347             mHasBlurEffect = true;
348             mValues[HAS_BLUR].setValue(1);
349         }
350         if (dataType == DATA_TYPE_FLOAT) {
351             float value = buffer.readFloat();
352             mValues[index].setValue(value);
353         } else if (dataType == DATA_TYPE_INT) {
354             int value = buffer.readInt();
355             mValues[index].setValue(value);
356         }
357     }
358 
359     /**
360      * Populate the documentation with a description of this operation
361      *
362      * @param doc to append the description to.
363      */
documentation(DocumentationBuilder doc)364     public static void documentation(DocumentationBuilder doc) {
365         doc.operation("Modifier Operations", OP_CODE, CLASS_NAME)
366                 .description("define the GraphicsLayer Modifier");
367     }
368 
369     @Override
layout(RemoteContext context, Component component, float width, float height)370     public void layout(RemoteContext context, Component component, float width, float height) {}
371 
372     @Override
serialize(MapSerializer serializer)373     public void serialize(MapSerializer serializer) {
374         serializer
375                 .addTags(SerializeTags.MODIFIER)
376                 .addType("GraphicsLayerModifierOperation")
377                 .add("scaleX", mValues[SCALE_X].getValue())
378                 .add("scaleY", mValues[SCALE_Y].getValue())
379                 .add("rotationX", mValues[ROTATION_X].getValue())
380                 .add("rotationY", mValues[ROTATION_Y].getValue())
381                 .add("rotationZ", mValues[ROTATION_Z].getValue())
382                 .add("shadowElevation", mValues[SHADOW_ELEVATION].getValue())
383                 .add("transformOriginX", mValues[TRANSFORM_ORIGIN_X].getValue())
384                 .add("transformOriginY", mValues[TRANSFORM_ORIGIN_Y].getValue())
385                 .add("translationX", mValues[TRANSLATION_X].getValue())
386                 .add("translationY", mValues[TRANSLATION_Y].getValue())
387                 .add("translationZ", mValues[TRANSLATION_Z].getValue())
388                 .add("alpha", mValues[ALPHA].getValue())
389                 .add("cameraDistance", mValues[CAMERA_DISTANCE].getValue())
390                 .add("compositingStrategy", mValues[COMPOSITING_STRATEGY].getIntValue())
391                 .add("spotShadowColorId", mValues[SPOT_SHADOW_COLOR].getIntValue())
392                 .add("ambientShadowColorId", mValues[AMBIENT_SHADOW_COLOR].getIntValue());
393     }
394 }
395