diff options
112 files changed, 7278 insertions, 2795 deletions
diff --git a/core/java/com/android/internal/widget/remotecompose/core/CompanionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/CompanionOperation.java index 2d365368a013..deae9a571e12 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/CompanionOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/CompanionOperation.java @@ -27,9 +27,5 @@ public interface CompanionOperation { * @param operations command is to be added */ void read(WireBuffer buffer, List<Operation> operations); - - // Debugging / Documentation utility functions - String name(); - int id(); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/CoreDocument.java b/core/java/com/android/internal/widget/remotecompose/core/CoreDocument.java index effbbe2f0c1d..18be4809998c 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/CoreDocument.java +++ b/core/java/com/android/internal/widget/remotecompose/core/CoreDocument.java @@ -15,16 +15,23 @@ */ package com.android.internal.widget.remotecompose.core; +import com.android.internal.widget.remotecompose.core.operations.ComponentValue; import com.android.internal.widget.remotecompose.core.operations.NamedVariable; import com.android.internal.widget.remotecompose.core.operations.RootContentBehavior; import com.android.internal.widget.remotecompose.core.operations.Theme; +import com.android.internal.widget.remotecompose.core.operations.layout.ClickModifierEnd; +import com.android.internal.widget.remotecompose.core.operations.layout.ClickModifierOperation; import com.android.internal.widget.remotecompose.core.operations.layout.Component; import com.android.internal.widget.remotecompose.core.operations.layout.ComponentEnd; import com.android.internal.widget.remotecompose.core.operations.layout.ComponentStartOperation; import com.android.internal.widget.remotecompose.core.operations.layout.LayoutComponent; import com.android.internal.widget.remotecompose.core.operations.layout.RootLayoutComponent; +import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ComponentModifiers; +import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ModifierOperation; +import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer; import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.Set; @@ -34,6 +41,8 @@ import java.util.Set; */ public class CoreDocument { + private static final boolean DEBUG = false; + ArrayList<Operation> mOperations; RootLayoutComponent mRootLayoutComponent = null; @@ -57,6 +66,8 @@ public class CoreDocument { RemoteComposeBuffer mBuffer = new RemoteComposeBuffer(mRemoteComposeState); + private int mLastId = 1; // last component id when inflating the file + public String getContentDescription() { return mContentDescription; } @@ -303,6 +314,59 @@ public class CoreDocument { return null; } + /** + * Returns a string representation of the component hierarchy of the document + * + * @return a standardized string representation of the component hierarchy + */ + public String displayHierarchy() { + StringSerializer serializer = new StringSerializer(); + for (Operation op : mOperations) { + if (op instanceof RootLayoutComponent) { + ((RootLayoutComponent) op).displayHierarchy((Component) op, 0, serializer); + } else if (op instanceof SerializableToString) { + ((SerializableToString) op).serializeToString(0, serializer); + } + } + return serializer.toString(); + } + + /** + * Callback interface for host actions + */ + public interface ActionCallback { + // TODO: add payload support + void onAction(String name); + } + + HashSet<ActionCallback> mActionListeners = new HashSet<ActionCallback>(); + + /** + * Warn action listeners for the given named action + * @param name the action name + */ + public void runNamedAction(String name) { + for (ActionCallback callback : mActionListeners) { + callback.onAction(name); + } + } + + /** + * Add a callback for handling the named host actions + * + * @param callback + */ + public void addActionCallback(ActionCallback callback) { + mActionListeners.add(callback); + } + + /** + * Clear existing callbacks for named host actions + */ + public void clearActionCallbacks() { + mActionListeners.clear(); + } + public interface ClickCallbacks { void click(int id, String metadata); } @@ -403,7 +467,7 @@ public class CoreDocument { } } if (mRootLayoutComponent != null) { - mRootLayoutComponent.assignIds(); + mRootLayoutComponent.assignIds(mLastId); } } @@ -417,7 +481,9 @@ public class CoreDocument { ArrayList<Component> components = new ArrayList<>(); ArrayList<Operation> finalOperationsList = new ArrayList<>(); ArrayList<Operation> ops = finalOperationsList; + ClickModifierOperation currentClickModifier = null; + mLastId = -1; for (Operation o : operations) { if (o instanceof ComponentStartOperation) { Component component = (Component) o; @@ -426,6 +492,9 @@ public class CoreDocument { currentComponent = component; ops.add(currentComponent); ops = currentComponent.getList(); + if (component.getComponentId() < mLastId) { + mLastId = component.getComponentId(); + } } else if (o instanceof ComponentEnd) { if (currentComponent instanceof LayoutComponent) { ((LayoutComponent) currentComponent).inflate(); @@ -437,6 +506,14 @@ public class CoreDocument { } else { ops = finalOperationsList; } + } else if (o instanceof ClickModifierOperation) { + // TODO: refactor to add container <- component... + currentClickModifier = (ClickModifierOperation) o; + ops = ((ClickModifierOperation) o).getList(); + } else if (o instanceof ClickModifierEnd) { + ops = currentComponent.getList(); + ops.add(currentClickModifier); + currentClickModifier = null; } else { ops.add(o); } @@ -444,12 +521,46 @@ public class CoreDocument { return ops; } + private HashMap<Integer, Component> mComponentMap = new HashMap<Integer, Component>(); + + private void registerVariables(RemoteContext context, ArrayList<Operation> list) { + for (Operation op : list) { + if (op instanceof VariableSupport) { + ((VariableSupport) op).updateVariables(context); + ((VariableSupport) op).registerListening(context); + } + if (op instanceof Component) { + mComponentMap.put(((Component) op).getComponentId(), (Component) op); + registerVariables(context, ((Component) op).getList()); + } + if (op instanceof ComponentValue) { + ComponentValue v = (ComponentValue) op; + Component component = mComponentMap.get(v.getComponentId()); + if (component != null) { + component.addComponentValue(v); + } else { + System.out.println("=> Component not found for id " + v.getComponentId()); + } + } + if (op instanceof ComponentModifiers) { + for (ModifierOperation modifier : ((ComponentModifiers) op).getList()) { + if (modifier instanceof VariableSupport) { + ((VariableSupport) modifier).updateVariables(context); + ((VariableSupport) modifier).registerListening(context); + } + } + } + op.apply(context); + } + } + /** * Called when an initialization is needed, allowing the document to eg load * resources / cache them. */ public void initializeContext(RemoteContext context) { mRemoteComposeState.reset(); + mRemoteComposeState.setContext(context); mClickAreas.clear(); mRemoteComposeState.setNextId(RemoteComposeState.START_ID); context.mDocument = this; @@ -458,15 +569,8 @@ public class CoreDocument { context.mMode = RemoteContext.ContextMode.DATA; mTimeVariables.updateTime(context); - for (Operation op : mOperations) { - if (op instanceof VariableSupport) { - ((VariableSupport) op).updateVariables(context); - ((VariableSupport) op).registerListening(context); - } - op.apply(context); - } + registerVariables(context, mOperations); context.mMode = RemoteContext.ContextMode.UNSET; - } /////////////////////////////////////////////////////////////////////////////////////////////// @@ -529,15 +633,27 @@ public class CoreDocument { } /** + * Returns the list of set click listeners + * + * @return set of click listeners + */ + public HashSet<CoreDocument.ClickCallbacks> getClickListeners() { + return mClickListeners; + } + + /** * Passing a click event to the document. This will possibly result in calling the click * listeners. */ - public void onClick(float x, float y) { + public void onClick(RemoteContext context, float x, float y) { for (ClickAreaRepresentation clickArea : mClickAreas) { if (clickArea.contains(x, y)) { warnClickListeners(clickArea); } } + if (mRootLayoutComponent != null) { + mRootLayoutComponent.onClick(context, this, x, y); + } } /** @@ -551,6 +667,9 @@ public class CoreDocument { warnClickListeners(clickArea); } } + for (ClickCallbacks listener : mClickListeners) { + listener.click(id, ""); + } } /** @@ -627,13 +746,17 @@ public class CoreDocument { * @param theme the theme we want to use for this document. */ public void paint(RemoteContext context, int theme) { - context.mMode = RemoteContext.ContextMode.PAINT; + long time = System.nanoTime(); + context.getPaintContext().clearNeedsRepaint(); + context.mMode = RemoteContext.ContextMode.UNSET; // current theme starts as UNSPECIFIED, until a Theme setter // operation gets executed and modify it. context.setTheme(Theme.UNSPECIFIED); context.mRemoteComposeState = mRemoteComposeState; + context.mRemoteComposeState.setContext(context); + if (mContentSizing == RootContentBehavior.SIZING_SCALE) { // we need to add canvas transforms ops here computeScale(context.mWidth, context.mHeight, mScaleOutput); @@ -643,8 +766,8 @@ public class CoreDocument { context.mPaintContext.scale(mScaleOutput[0], mScaleOutput[1]); } mTimeVariables.updateTime(context); - context.loadFloat(RemoteContext.ID_WINDOW_WIDTH, getWidth()); - context.loadFloat(RemoteContext.ID_WINDOW_HEIGHT, getHeight()); + context.loadFloat(RemoteContext.ID_WINDOW_WIDTH, context.mWidth); + context.loadFloat(RemoteContext.ID_WINDOW_HEIGHT, context.mHeight); mRepaintNext = context.updateOps(); if (mRootLayoutComponent != null) { if (context.mWidth != mRootLayoutComponent.getWidth() @@ -654,10 +777,19 @@ public class CoreDocument { if (mRootLayoutComponent.needsMeasure()) { mRootLayoutComponent.layout(context); } + // TODO -- this should be specifically about applying animation, not paint + mRootLayoutComponent.paint(context.getPaintContext()); + // TODO -- should be able to remove this + mRootLayoutComponent.updateVariables(context); + if (DEBUG) { + String hierarchy = mRootLayoutComponent.displayHierarchy(); + System.out.println(hierarchy); + } if (mRootLayoutComponent.doesNeedsRepaint()) { mRepaintNext = 1; } } + context.mMode = RemoteContext.ContextMode.PAINT; for (Operation op : mOperations) { // operations will only be executed if no theme is set (ie UNSPECIFIED) // or the theme is equal as the one passed in argument to paint. @@ -671,8 +803,95 @@ public class CoreDocument { op.apply(context); } } + if (context.getPaintContext().doesNeedsRepaint() + || (mRootLayoutComponent != null && mRootLayoutComponent.doesNeedsRepaint())) { + mRepaintNext = 1; + } context.mMode = RemoteContext.ContextMode.UNSET; + // System.out.println(">> " + ( System.nanoTime() - time)*1E-6f+" ms"); + } + + public String[] getStats() { + ArrayList<String> ret = new ArrayList<>(); + WireBuffer buffer = new WireBuffer(); + int count = mOperations.size(); + HashMap<String, int[]> map = new HashMap<>(); + for (Operation mOperation : mOperations) { + Class<? extends Operation> c = mOperation.getClass(); + int[] values; + if (map.containsKey(c.getSimpleName())) { + values = map.get(c.getSimpleName()); + } else { + values = new int[2]; + map.put(c.getSimpleName(), values); + } + + values[0] += 1; + values[1] += sizeOfComponent(mOperation, buffer); + if (mOperation instanceof Component) { + Component com = (Component) mOperation; + count += addChildren(com, map, buffer); + + } + } + + ret.add(0, "number of operations : " + count); + + for (String s : map.keySet()) { + int[] v = map.get(s); + ret.add(s + " : " + v[0] + ":" + v[1]); + } + return ret.toArray(new String[0]); + } + + private int sizeOfComponent(Operation com, WireBuffer tmp) { + tmp.reset(100); + com.write(tmp); + int size = tmp.getSize(); + tmp.reset(100); + return size; } + private int addChildren(Component base, HashMap<String, int[]> map, WireBuffer tmp) { + int count = base.mList.size(); + for (Operation mOperation : base.mList) { + Class<? extends Operation> c = mOperation.getClass(); + int[] values; + if (map.containsKey(c.getSimpleName())) { + values = map.get(c.getSimpleName()); + } else { + values = new int[2]; + map.put(c.getSimpleName(), values); + } + values[0] += 1; + values[1] += sizeOfComponent(mOperation, tmp); + if (mOperation instanceof Component) { + count += addChildren((Component) mOperation, map, tmp); + } + } + return count; + } + + public String toNestedString() { + StringBuilder ret = new StringBuilder(); + for (Operation mOperation : mOperations) { + ret.append(mOperation.toString()); + ret.append("\n"); + if (mOperation instanceof Component) { + toNestedString((Component) mOperation, ret, " "); + } + } + return ret.toString(); + } + + private void toNestedString(Component base, StringBuilder ret, String indent) { + for (Operation mOperation : base.mList) { + ret.append(mOperation.toString()); + ret.append("\n"); + if (mOperation instanceof Component) { + toNestedString((Component) mOperation, ret, indent + " "); + } + } + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/DocumentedCompanion.java b/core/java/com/android/internal/widget/remotecompose/core/DocumentedCompanion.java new file mode 100644 index 000000000000..661cf7cf4491 --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/DocumentedCompanion.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget.remotecompose.core; + +import com.android.internal.widget.remotecompose.core.documentation.DocumentedCompanionOperation; + +public interface DocumentedCompanion extends CompanionOperation , DocumentedCompanionOperation { + +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/Operations.java b/core/java/com/android/internal/widget/remotecompose/core/Operations.java index 9cb024bd234e..4a25b5eff3c9 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/Operations.java +++ b/core/java/com/android/internal/widget/remotecompose/core/Operations.java @@ -21,6 +21,10 @@ import com.android.internal.widget.remotecompose.core.operations.ClipPath; import com.android.internal.widget.remotecompose.core.operations.ClipRect; import com.android.internal.widget.remotecompose.core.operations.ColorConstant; import com.android.internal.widget.remotecompose.core.operations.ColorExpression; +import com.android.internal.widget.remotecompose.core.operations.ComponentValue; +import com.android.internal.widget.remotecompose.core.operations.DataListFloat; +import com.android.internal.widget.remotecompose.core.operations.DataListIds; +import com.android.internal.widget.remotecompose.core.operations.DataMapIds; import com.android.internal.widget.remotecompose.core.operations.DrawArc; import com.android.internal.widget.remotecompose.core.operations.DrawBitmap; import com.android.internal.widget.remotecompose.core.operations.DrawBitmapInt; @@ -54,24 +58,35 @@ import com.android.internal.widget.remotecompose.core.operations.TextData; import com.android.internal.widget.remotecompose.core.operations.TextFromFloat; import com.android.internal.widget.remotecompose.core.operations.TextMerge; import com.android.internal.widget.remotecompose.core.operations.Theme; +import com.android.internal.widget.remotecompose.core.operations.layout.CanvasContent; +import com.android.internal.widget.remotecompose.core.operations.layout.ClickModifierEnd; +import com.android.internal.widget.remotecompose.core.operations.layout.ClickModifierOperation; import com.android.internal.widget.remotecompose.core.operations.layout.ComponentEnd; import com.android.internal.widget.remotecompose.core.operations.layout.ComponentStart; import com.android.internal.widget.remotecompose.core.operations.layout.LayoutComponentContent; import com.android.internal.widget.remotecompose.core.operations.layout.RootLayoutComponent; import com.android.internal.widget.remotecompose.core.operations.layout.animation.AnimationSpec; import com.android.internal.widget.remotecompose.core.operations.layout.managers.BoxLayout; +import com.android.internal.widget.remotecompose.core.operations.layout.managers.CanvasLayout; import com.android.internal.widget.remotecompose.core.operations.layout.managers.ColumnLayout; import com.android.internal.widget.remotecompose.core.operations.layout.managers.RowLayout; +import com.android.internal.widget.remotecompose.core.operations.layout.managers.TextLayout; import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.BackgroundModifierOperation; import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.BorderModifierOperation; import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ClipRectModifierOperation; +import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ComponentVisibilityOperation; import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.HeightModifierOperation; +import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.HostActionOperation; +import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.HostNamedActionOperation; import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.PaddingModifierOperation; import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.RoundedClipRectModifierOperation; +import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ValueIntegerChangeActionOperation; +import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ValueStringChangeActionOperation; import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.WidthModifierOperation; import com.android.internal.widget.remotecompose.core.operations.utilities.IntMap; import com.android.internal.widget.remotecompose.core.types.BooleanConstant; import com.android.internal.widget.remotecompose.core.types.IntegerConstant; +import com.android.internal.widget.remotecompose.core.types.LongConstant; /** * List of operations supported in a RemoteCompose document @@ -130,6 +145,10 @@ public class Operations { public static final int DATA_INT = 140; public static final int DATA_BOOLEAN = 143; public static final int INTEGER_EXPRESSION = 144; + public static final int ID_MAP = 145; + public static final int ID_LIST = 146; + public static final int FLOAT_LIST = 147; + public static final int DATA_LONG = 148; /////////////////////////////////////////====================== @@ -142,6 +161,10 @@ public class Operations { public static final int LAYOUT_BOX = 202; public static final int LAYOUT_ROW = 203; public static final int LAYOUT_COLUMN = 204; + public static final int LAYOUT_CANVAS = 205; + public static final int LAYOUT_CANVAS_CONTENT = 207; + + public static final int LAYOUT_TEXT = 208; public static final int COMPONENT_START = 2; public static final int COMPONENT_END = 3; public static final int MODIFIER_WIDTH = 16; @@ -151,73 +174,110 @@ public class Operations { public static final int MODIFIER_PADDING = 58; public static final int MODIFIER_CLIP_RECT = 108; public static final int MODIFIER_ROUNDED_CLIP_RECT = 54; + + public static final int MODIFIER_CLICK = 59; + + public static final int MODIFIER_CLICK_END = 214; + + public static final int MODIFIER_VISIBILITY = 211; + public static final int HOST_ACTION = 209; + public static final int HOST_NAMED_ACTION = 210; + + public static final int VALUE_INTEGER_CHANGE_ACTION = 212; + public static final int VALUE_STRING_CHANGE_ACTION = 213; + public static final int ANIMATION_SPEC = 14; - public static IntMap<CompanionOperation> map = new IntMap<>(); + public static final int COMPONENT_VALUE = 150; + + public static UniqueIntMap<CompanionOperation> map = new UniqueIntMap<>(); + + static class UniqueIntMap<T> extends IntMap<T> { + @Override + public T put(int key, T value) { + assert null == get(key) : "Opcode " + key + " already used in Operations !"; + return super.put(key, value); + } + } static { - map.put(HEADER, Header.COMPANION); - map.put(DRAW_BITMAP_INT, DrawBitmapInt.COMPANION); - map.put(DATA_BITMAP, BitmapData.COMPANION); - map.put(DATA_TEXT, TextData.COMPANION); - map.put(THEME, Theme.COMPANION); - map.put(CLICK_AREA, ClickArea.COMPANION); - map.put(ROOT_CONTENT_BEHAVIOR, RootContentBehavior.COMPANION); - map.put(ROOT_CONTENT_DESCRIPTION, RootContentDescription.COMPANION); - - map.put(DRAW_ARC, DrawArc.COMPANION); - map.put(DRAW_BITMAP, DrawBitmap.COMPANION); - map.put(DRAW_CIRCLE, DrawCircle.COMPANION); - map.put(DRAW_LINE, DrawLine.COMPANION); - map.put(DRAW_OVAL, DrawOval.COMPANION); - map.put(DRAW_PATH, DrawPath.COMPANION); - map.put(DRAW_RECT, DrawRect.COMPANION); - map.put(DRAW_ROUND_RECT, DrawRoundRect.COMPANION); - map.put(DRAW_TEXT_ON_PATH, DrawTextOnPath.COMPANION); - map.put(DRAW_TEXT_RUN, DrawText.COMPANION); - map.put(DRAW_TWEEN_PATH, DrawTweenPath.COMPANION); - map.put(DATA_PATH, PathData.COMPANION); - map.put(PAINT_VALUES, PaintData.COMPANION); - map.put(MATRIX_RESTORE, MatrixRestore.COMPANION); - map.put(MATRIX_ROTATE, MatrixRotate.COMPANION); - map.put(MATRIX_SAVE, MatrixSave.COMPANION); - map.put(MATRIX_SCALE, MatrixScale.COMPANION); - map.put(MATRIX_SKEW, MatrixSkew.COMPANION); - map.put(MATRIX_TRANSLATE, MatrixTranslate.COMPANION); - map.put(CLIP_PATH, ClipPath.COMPANION); - map.put(CLIP_RECT, ClipRect.COMPANION); - map.put(DATA_SHADER, ShaderData.COMPANION); - map.put(DATA_FLOAT, FloatConstant.COMPANION); - map.put(ANIMATED_FLOAT, FloatExpression.COMPANION); - map.put(DRAW_TEXT_ANCHOR, DrawTextAnchored.COMPANION); - map.put(COLOR_EXPRESSIONS, ColorExpression.COMPANION); - map.put(TEXT_FROM_FLOAT, TextFromFloat.COMPANION); - map.put(TEXT_MERGE, TextMerge.COMPANION); - map.put(NAMED_VARIABLE, NamedVariable.COMPANION); - map.put(COLOR_CONSTANT, ColorConstant.COMPANION); - map.put(DATA_INT, IntegerConstant.COMPANION); - map.put(INTEGER_EXPRESSION, IntegerExpression.COMPANION); - map.put(DATA_BOOLEAN, BooleanConstant.COMPANION); + map.put(HEADER, Header::read); + map.put(DRAW_BITMAP_INT, DrawBitmapInt::read); + map.put(DATA_BITMAP, BitmapData::read); + map.put(DATA_TEXT, TextData::read); + map.put(THEME, Theme::read); + map.put(CLICK_AREA, ClickArea::read); + map.put(ROOT_CONTENT_BEHAVIOR, RootContentBehavior::read); + map.put(ROOT_CONTENT_DESCRIPTION, RootContentDescription::read); + + map.put(DRAW_ARC, DrawArc::read); + map.put(DRAW_BITMAP, DrawBitmap::read); + map.put(DRAW_CIRCLE, DrawCircle::read); + map.put(DRAW_LINE, DrawLine::read); + map.put(DRAW_OVAL, DrawOval::read); + map.put(DRAW_PATH, DrawPath::read); + map.put(DRAW_RECT, DrawRect::read); + map.put(DRAW_ROUND_RECT, DrawRoundRect::read); + map.put(DRAW_TEXT_ON_PATH, DrawTextOnPath::read); + map.put(DRAW_TEXT_RUN, DrawText::read); + map.put(DRAW_TWEEN_PATH, DrawTweenPath::read); + map.put(DATA_PATH, PathData::read); + map.put(PAINT_VALUES, PaintData::read); + map.put(MATRIX_RESTORE, MatrixRestore::read); + map.put(MATRIX_ROTATE, MatrixRotate::read); + map.put(MATRIX_SAVE, MatrixSave::read); + map.put(MATRIX_SCALE, MatrixScale::read); + map.put(MATRIX_SKEW, MatrixSkew::read); + map.put(MATRIX_TRANSLATE, MatrixTranslate::read); + map.put(CLIP_PATH, ClipPath::read); + map.put(CLIP_RECT, ClipRect::read); + map.put(DATA_SHADER, ShaderData::read); + map.put(DATA_FLOAT, FloatConstant::read); + map.put(ANIMATED_FLOAT, FloatExpression::read); + map.put(DRAW_TEXT_ANCHOR, DrawTextAnchored::read); + map.put(COLOR_EXPRESSIONS, ColorExpression::read); + map.put(TEXT_FROM_FLOAT, TextFromFloat::read); + map.put(TEXT_MERGE, TextMerge::read); + map.put(NAMED_VARIABLE, NamedVariable::read); + map.put(COLOR_CONSTANT, ColorConstant::read); + map.put(DATA_INT, IntegerConstant::read); + map.put(INTEGER_EXPRESSION, IntegerExpression::read); + map.put(DATA_BOOLEAN, BooleanConstant::read); + map.put(ID_MAP, DataMapIds::read); + map.put(ID_LIST, DataListIds::read); + map.put(FLOAT_LIST, DataListFloat::read); + map.put(DATA_LONG, LongConstant::read); // Layout - map.put(COMPONENT_START, ComponentStart.COMPANION); - map.put(COMPONENT_END, ComponentEnd.COMPANION); - map.put(ANIMATION_SPEC, AnimationSpec.COMPANION); - - map.put(MODIFIER_WIDTH, WidthModifierOperation.COMPANION); - map.put(MODIFIER_HEIGHT, HeightModifierOperation.COMPANION); - map.put(MODIFIER_PADDING, PaddingModifierOperation.COMPANION); - map.put(MODIFIER_BACKGROUND, BackgroundModifierOperation.COMPANION); - map.put(MODIFIER_BORDER, BorderModifierOperation.COMPANION); - map.put(MODIFIER_ROUNDED_CLIP_RECT, RoundedClipRectModifierOperation.COMPANION); - map.put(MODIFIER_CLIP_RECT, ClipRectModifierOperation.COMPANION); - - map.put(LAYOUT_ROOT, RootLayoutComponent.COMPANION); - map.put(LAYOUT_CONTENT, LayoutComponentContent.COMPANION); - map.put(LAYOUT_BOX, BoxLayout.COMPANION); - map.put(LAYOUT_COLUMN, ColumnLayout.COMPANION); - map.put(LAYOUT_ROW, RowLayout.COMPANION); - } + map.put(COMPONENT_START, ComponentStart::read); + map.put(COMPONENT_END, ComponentEnd::read); + map.put(ANIMATION_SPEC, AnimationSpec::read); + map.put(MODIFIER_WIDTH, WidthModifierOperation::read); + map.put(MODIFIER_HEIGHT, HeightModifierOperation::read); + map.put(MODIFIER_PADDING, PaddingModifierOperation::read); + map.put(MODIFIER_BACKGROUND, BackgroundModifierOperation::read); + map.put(MODIFIER_BORDER, BorderModifierOperation::read); + map.put(MODIFIER_ROUNDED_CLIP_RECT, RoundedClipRectModifierOperation::read); + map.put(MODIFIER_CLIP_RECT, ClipRectModifierOperation::read); + map.put(MODIFIER_CLICK, ClickModifierOperation::read); + map.put(MODIFIER_CLICK_END, ClickModifierEnd::read); + map.put(MODIFIER_VISIBILITY, ComponentVisibilityOperation::read); + map.put(HOST_ACTION, HostActionOperation::read); + map.put(HOST_NAMED_ACTION, HostNamedActionOperation::read); + map.put(VALUE_INTEGER_CHANGE_ACTION, ValueIntegerChangeActionOperation::read); + map.put(VALUE_STRING_CHANGE_ACTION, ValueStringChangeActionOperation::read); + + map.put(LAYOUT_ROOT, RootLayoutComponent::read); + map.put(LAYOUT_CONTENT, LayoutComponentContent::read); + map.put(LAYOUT_BOX, BoxLayout::read); + map.put(LAYOUT_COLUMN, ColumnLayout::read); + map.put(LAYOUT_ROW, RowLayout::read); + map.put(LAYOUT_CANVAS, CanvasLayout::read); + map.put(LAYOUT_CANVAS_CONTENT, CanvasContent::read); + map.put(LAYOUT_TEXT, TextLayout::read); + + map.put(COMPONENT_VALUE, ComponentValue::read); + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/PaintContext.java b/core/java/com/android/internal/widget/remotecompose/core/PaintContext.java index 665fcb749db8..4770b122d172 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/PaintContext.java +++ b/core/java/com/android/internal/widget/remotecompose/core/PaintContext.java @@ -21,12 +21,23 @@ import com.android.internal.widget.remotecompose.core.operations.paint.PaintBund * Specify an abstract paint context used by RemoteCompose commands to draw */ public abstract class PaintContext { - protected RemoteContext mContext; + public static final int TEXT_MEASURE_MONOSPACE_WIDTH = 0x01; + public static final int TEXT_MEASURE_FONT_HEIGHT = 0x02; + protected RemoteContext mContext; + private boolean mNeedsRepaint = false; public RemoteContext getContext() { return mContext; } + public boolean doesNeedsRepaint() { + return mNeedsRepaint; + } + + public void clearNeedsRepaint() { + mNeedsRepaint = false; + } + public PaintContext(RemoteContext context) { this.mContext = context; } @@ -111,13 +122,16 @@ public abstract class PaintContext { * @param textId * @param start * @param end if end is -1 it means the whole string - * @param monospace measure with better support for monospace + * @param flags how to measure: + * TEXT_MEASURE_MONOSPACE_WIDTH - measure as a monospace font + * TEXT_MEASURE_FULL_HEIGHT - measure bounds of the given string using the + * max ascend and descent of the font (not just of the measured text) * @param bounds the bounds (left, top, right, bottom) */ public abstract void getTextBounds(int textId, int start, int end, - boolean monospace, + int flags, float[]bounds); /** @@ -267,5 +281,8 @@ public abstract class PaintContext { System.out.println("[LOG] " + content); } + public void needsRepaint() { + mNeedsRepaint = true; + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java b/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java index 333951ba2386..6b1828f0448f 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java +++ b/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java @@ -21,6 +21,10 @@ import com.android.internal.widget.remotecompose.core.operations.ClipPath; import com.android.internal.widget.remotecompose.core.operations.ClipRect; import com.android.internal.widget.remotecompose.core.operations.ColorConstant; import com.android.internal.widget.remotecompose.core.operations.ColorExpression; +import com.android.internal.widget.remotecompose.core.operations.ComponentValue; +import com.android.internal.widget.remotecompose.core.operations.DataListFloat; +import com.android.internal.widget.remotecompose.core.operations.DataListIds; +import com.android.internal.widget.remotecompose.core.operations.DataMapIds; import com.android.internal.widget.remotecompose.core.operations.DrawArc; import com.android.internal.widget.remotecompose.core.operations.DrawBitmap; import com.android.internal.widget.remotecompose.core.operations.DrawBitmapInt; @@ -54,19 +58,23 @@ import com.android.internal.widget.remotecompose.core.operations.TextFromFloat; import com.android.internal.widget.remotecompose.core.operations.TextMerge; import com.android.internal.widget.remotecompose.core.operations.Theme; import com.android.internal.widget.remotecompose.core.operations.Utils; +import com.android.internal.widget.remotecompose.core.operations.layout.CanvasContent; import com.android.internal.widget.remotecompose.core.operations.layout.ComponentEnd; import com.android.internal.widget.remotecompose.core.operations.layout.ComponentStart; import com.android.internal.widget.remotecompose.core.operations.layout.LayoutComponentContent; import com.android.internal.widget.remotecompose.core.operations.layout.RootLayoutComponent; import com.android.internal.widget.remotecompose.core.operations.layout.managers.BoxLayout; +import com.android.internal.widget.remotecompose.core.operations.layout.managers.CanvasLayout; import com.android.internal.widget.remotecompose.core.operations.layout.managers.ColumnLayout; import com.android.internal.widget.remotecompose.core.operations.layout.managers.RowLayout; +import com.android.internal.widget.remotecompose.core.operations.layout.managers.TextLayout; import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.BackgroundModifierOperation; import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.BorderModifierOperation; import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ClipRectModifierOperation; import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.PaddingModifierOperation; import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.RoundedClipRectModifierOperation; import com.android.internal.widget.remotecompose.core.operations.paint.PaintBundle; +import com.android.internal.widget.remotecompose.core.operations.utilities.NanMap; import com.android.internal.widget.remotecompose.core.operations.utilities.easing.FloatAnimation; import com.android.internal.widget.remotecompose.core.types.IntegerConstant; @@ -97,6 +105,9 @@ public class RemoteComposeBuffer { RemoteComposeState mRemoteComposeState; private static final boolean DEBUG = false; + private int mLastComponentId = 0; + private int mGeneratedComponentId = -1; + /** * Provides an abstract buffer to encode/decode RemoteCompose operations * @@ -114,6 +125,12 @@ public class RemoteComposeBuffer { public void reset(int expectedSize) { mBuffer.reset(expectedSize); mRemoteComposeState.reset(); + mLastComponentId = 0; + mGeneratedComponentId = -1; + } + + public int getLastComponentId() { + return mLastComponentId; } public Platform getPlatform() { @@ -146,11 +163,11 @@ public class RemoteComposeBuffer { */ public void header(int width, int height, String contentDescription, float density, long capabilities) { - Header.COMPANION.apply(mBuffer, width, height, density, capabilities); + Header.apply(mBuffer, width, height, density, capabilities); int contentDescriptionId = 0; if (contentDescription != null) { contentDescriptionId = addText(contentDescription); - RootContentDescription.COMPANION.apply(mBuffer, contentDescriptionId); + RootContentDescription.apply(mBuffer, contentDescriptionId); } } @@ -187,15 +204,15 @@ public class RemoteComposeBuffer { String contentDescription) { int imageId = mRemoteComposeState.dataGetId(image); if (imageId == -1) { - imageId = mRemoteComposeState.cache(image); + imageId = mRemoteComposeState.cacheData(image); byte[] data = mPlatform.imageToByteArray(image); - BitmapData.COMPANION.apply(mBuffer, imageId, imageWidth, imageHeight, data); + BitmapData.apply(mBuffer, imageId, imageWidth, imageHeight, data); } int contentDescriptionId = 0; if (contentDescription != null) { contentDescriptionId = addText(contentDescription); } - DrawBitmapInt.COMPANION.apply( + DrawBitmapInt.apply( mBuffer, imageId, srcLeft, srcTop, srcRight, srcBottom, dstLeft, dstTop, dstRight, dstBottom, contentDescriptionId ); @@ -210,8 +227,8 @@ public class RemoteComposeBuffer { public int addText(String text) { int id = mRemoteComposeState.dataGetId(text); if (id == -1) { - id = mRemoteComposeState.cache(text); - TextData.COMPANION.apply(mBuffer, id, text); + id = mRemoteComposeState.cacheData(text); + TextData.apply(mBuffer, id, text); } return id; } @@ -244,7 +261,7 @@ public class RemoteComposeBuffer { if (metadata != null) { metadataId = addText(metadata); } - ClickArea.COMPANION.apply(mBuffer, id, contentDescriptionId, + ClickArea.apply(mBuffer, id, contentDescriptionId, left, top, right, bottom, metadataId); } @@ -268,7 +285,7 @@ public class RemoteComposeBuffer { * The LAYOUT_*_FIXED modes will use the intrinsic document size */ public void setRootContentBehavior(int scroll, int alignment, int sizing, int mode) { - RootContentBehavior.COMPANION.apply(mBuffer, scroll, alignment, sizing, mode); + RootContentBehavior.apply(mBuffer, scroll, alignment, sizing, mode); } /** @@ -298,7 +315,7 @@ public class RemoteComposeBuffer { float bottom, float startAngle, float sweepAngle) { - DrawArc.COMPANION.apply(mBuffer, left, top, right, bottom, startAngle, sweepAngle); + DrawArc.apply(mBuffer, left, top, right, bottom, startAngle, sweepAngle); } /** @@ -317,18 +334,18 @@ public class RemoteComposeBuffer { String contentDescription) { int imageId = mRemoteComposeState.dataGetId(image); if (imageId == -1) { - imageId = mRemoteComposeState.cache(image); + imageId = mRemoteComposeState.cacheData(image); byte[] data = mPlatform.imageToByteArray(image); int imageWidth = mPlatform.getImageWidth(image); int imageHeight = mPlatform.getImageHeight(image); - BitmapData.COMPANION.apply(mBuffer, imageId, imageWidth, imageHeight, data); + BitmapData.apply(mBuffer, imageId, imageWidth, imageHeight, data); } int contentDescriptionId = 0; if (contentDescription != null) { contentDescriptionId = addText(contentDescription); } - DrawBitmap.COMPANION.apply( + DrawBitmap.apply( mBuffer, imageId, left, top, right, bottom, contentDescriptionId ); } @@ -342,7 +359,7 @@ public class RemoteComposeBuffer { * @param radius The radius of the circle to be drawn */ public void addDrawCircle(float centerX, float centerY, float radius) { - DrawCircle.COMPANION.apply(mBuffer, centerX, centerY, radius); + DrawCircle.apply(mBuffer, centerX, centerY, radius); } /** @@ -355,7 +372,7 @@ public class RemoteComposeBuffer { * @param y2 The y-coordinate of the end point of the line */ public void addDrawLine(float x1, float y1, float x2, float y2) { - DrawLine.COMPANION.apply(mBuffer, x1, y1, x2, y2); + DrawLine.apply(mBuffer, x1, y1, x2, y2); } /** @@ -367,7 +384,7 @@ public class RemoteComposeBuffer { * @param bottom bottom coordinate of oval */ public void addDrawOval(float left, float top, float right, float bottom) { - DrawOval.COMPANION.apply(mBuffer, left, top, right, bottom); + DrawOval.apply(mBuffer, left, top, right, bottom); } /** @@ -392,7 +409,7 @@ public class RemoteComposeBuffer { * @param pathId */ public void addDrawPath(int pathId) { - DrawPath.COMPANION.apply(mBuffer, pathId); + DrawPath.apply(mBuffer, pathId); } /** @@ -404,7 +421,7 @@ public class RemoteComposeBuffer { * @param bottom bottom coordinate of rectangle to be drawn */ public void addDrawRect(float left, float top, float right, float bottom) { - DrawRect.COMPANION.apply(mBuffer, left, top, right, bottom); + DrawRect.apply(mBuffer, left, top, right, bottom); } /** @@ -419,7 +436,7 @@ public class RemoteComposeBuffer { */ public void addDrawRoundRect(float left, float top, float right, float bottom, float radiusX, float radiusY) { - DrawRoundRect.COMPANION.apply(mBuffer, left, top, right, bottom, radiusX, radiusY); + DrawRoundRect.apply(mBuffer, left, top, right, bottom, radiusX, radiusY); } /** @@ -436,7 +453,7 @@ public class RemoteComposeBuffer { pathId = addPathData(path); } int textId = addText(text); - DrawTextOnPath.COMPANION.apply(mBuffer, textId, pathId, hOffset, vOffset); + DrawTextOnPath.apply(mBuffer, textId, pathId, hOffset, vOffset); } /** @@ -461,7 +478,7 @@ public class RemoteComposeBuffer { float y, boolean rtl) { int textId = addText(text); - DrawText.COMPANION.apply( + DrawText.apply( mBuffer, textId, start, end, contextStart, contextEnd, x, y, rtl); } @@ -487,7 +504,7 @@ public class RemoteComposeBuffer { float x, float y, boolean rtl) { - DrawText.COMPANION.apply( + DrawText.apply( mBuffer, textId, start, end, contextStart, contextEnd, x, y, rtl); } @@ -520,7 +537,7 @@ public class RemoteComposeBuffer { float panY, int flags) { int textId = addText(text); - DrawTextAnchored.COMPANION.apply( + DrawTextAnchored.apply( mBuffer, textId, x, y, panX, panY, @@ -545,7 +562,7 @@ public class RemoteComposeBuffer { */ public int textMerge(int id1, int id2) { int textId = addText(id1 + "+" + id2); - TextMerge.COMPANION.apply(mBuffer, textId, id1, id2); + TextMerge.apply(mBuffer, textId, id1, id2); return textId; } @@ -571,10 +588,10 @@ public class RemoteComposeBuffer { + "(" + digitsBefore + "," + digitsAfter + "," + flags + ")"; int id = mRemoteComposeState.dataGetId(placeHolder); if (id == -1) { - id = mRemoteComposeState.cache(placeHolder); - // TextData.COMPANION.apply(mBuffer, id, text); + id = mRemoteComposeState.cacheData(placeHolder); + // TextData.apply(mBuffer, id, text); } - TextFromFloat.COMPANION.apply(mBuffer, id, value, digitsBefore, + TextFromFloat.apply(mBuffer, id, value, digitsBefore, digitsAfter, flags); return id; } @@ -607,7 +624,7 @@ public class RemoteComposeBuffer { float panY, int flags) { - DrawTextAnchored.COMPANION.apply( + DrawTextAnchored.apply( mBuffer, textId, x, y, panX, panY, @@ -655,7 +672,7 @@ public class RemoteComposeBuffer { float tween, float start, float stop) { - DrawTweenPath.COMPANION.apply( + DrawTweenPath.apply( mBuffer, path1Id, path2Id, tween, start, stop); } @@ -668,8 +685,8 @@ public class RemoteComposeBuffer { */ public int addPathData(Object path) { float[] pathData = mPlatform.pathToFloatArray(path); - int id = mRemoteComposeState.cache(path); - PathData.COMPANION.apply(mBuffer, id, pathData); + int id = mRemoteComposeState.cacheData(path); + PathData.apply(mBuffer, id, pathData); return id; } @@ -678,7 +695,7 @@ public class RemoteComposeBuffer { * @param paint */ public void addPaint(PaintBundle paint) { - PaintData.COMPANION.apply(mBuffer, paint); + PaintData.apply(mBuffer, paint); } /////////////////////////////////////////////////////////////////////////////////////////////// @@ -697,6 +714,18 @@ public class RemoteComposeBuffer { } } + public static void readNextOperation(WireBuffer buffer, ArrayList<Operation> operations) { + int opId = buffer.readByte(); + if (DEBUG) { + Utils.log(">> " + opId); + } + CompanionOperation operation = Operations.map.get(opId); + if (operation == null) { + throw new RuntimeException("Unknown operation encountered " + opId); + } + operation.read(buffer, operations); + } + RemoteComposeBuffer copy() { ArrayList<Operation> operations = new ArrayList<>(); inflateFromBuffer(operations); @@ -705,7 +734,7 @@ public class RemoteComposeBuffer { } public void setTheme(int theme) { - Theme.COMPANION.apply(mBuffer, theme); + Theme.apply(mBuffer, theme); } static String version() { @@ -743,6 +772,12 @@ public class RemoteComposeBuffer { return buffer; } + /** + * Write the given RemoteComposeBuffer to the given file + * + * @param buffer a RemoteComposeBuffer + * @param file a target file + */ public void write(RemoteComposeBuffer buffer, File file) { try { FileOutputStream fd = new FileOutputStream(file); @@ -750,7 +785,7 @@ public class RemoteComposeBuffer { fd.flush(); fd.close(); } catch (Exception ex) { - ex.printStackTrace(); + throw new RuntimeException(ex); } } @@ -766,8 +801,7 @@ public class RemoteComposeBuffer { System.arraycopy(bytes, 0, buffer.mBuffer.mBuffer, 0, bytes.length); buffer.mBuffer.mSize = bytes.length; } catch (Exception e) { - e.printStackTrace(); - // todo decide how to handel this stuff + throw new RuntimeException(e); } } @@ -794,7 +828,7 @@ public class RemoteComposeBuffer { * @param skewY The amount to skew in Y */ public void addMatrixSkew(float skewX, float skewY) { - MatrixSkew.COMPANION.apply(mBuffer, skewX, skewY); + MatrixSkew.apply(mBuffer, skewX, skewY); } /** @@ -803,7 +837,7 @@ public class RemoteComposeBuffer { * Do not call restore() more times than save() was called. */ public void addMatrixRestore() { - MatrixRestore.COMPANION.apply(mBuffer); + MatrixRestore.apply(mBuffer); } /** @@ -815,7 +849,7 @@ public class RemoteComposeBuffer { * existed before the save() will be reinstated. */ public void addMatrixSave() { - MatrixSave.COMPANION.apply(mBuffer); + MatrixSave.apply(mBuffer); } /** @@ -826,7 +860,7 @@ public class RemoteComposeBuffer { * @param centerY The y-coord for the pivot point (unchanged by the rotation) */ public void addMatrixRotate(float angle, float centerX, float centerY) { - MatrixRotate.COMPANION.apply(mBuffer, angle, centerX, centerY); + MatrixRotate.apply(mBuffer, angle, centerX, centerY); } /** @@ -836,7 +870,7 @@ public class RemoteComposeBuffer { * @param dy The distance to translate in Y */ public void addMatrixTranslate(float dx, float dy) { - MatrixTranslate.COMPANION.apply(mBuffer, dx, dy); + MatrixTranslate.apply(mBuffer, dx, dy); } /** @@ -846,7 +880,7 @@ public class RemoteComposeBuffer { * @param scaleY The amount to scale in Y */ public void addMatrixScale(float scaleX, float scaleY) { - MatrixScale.COMPANION.apply(mBuffer, scaleX, scaleY, Float.NaN, Float.NaN); + MatrixScale.apply(mBuffer, scaleX, scaleY, Float.NaN, Float.NaN); } /** @@ -858,7 +892,7 @@ public class RemoteComposeBuffer { * @param centerY The y-coord for the pivot point (unchanged by the scale) */ public void addMatrixScale(float scaleX, float scaleY, float centerX, float centerY) { - MatrixScale.COMPANION.apply(mBuffer, scaleX, scaleY, centerX, centerY); + MatrixScale.apply(mBuffer, scaleX, scaleY, centerX, centerY); } /** @@ -866,47 +900,47 @@ public class RemoteComposeBuffer { * @param pathId 0 clears the clip */ public void addClipPath(int pathId) { - ClipPath.COMPANION.apply(mBuffer, pathId); + ClipPath.apply(mBuffer, pathId); } /** - * Sets the clip based on clip rect - * @param left - * @param top - * @param right - * @param bottom + * Sets the clip based on clip rec + * @param left left coordinate of the clip rectangle + * @param top top coordinate of the clip rectangle + * @param right right coordinate of the clip rectangle + * @param bottom bottom coordinate of the clip rectangle */ public void addClipRect(float left, float top, float right, float bottom) { - ClipRect.COMPANION.apply(mBuffer, left, top, right, bottom); + ClipRect.apply(mBuffer, left, top, right, bottom); } /** * Add a float return a NaN number pointing to that float - * @param value - * @return + * @param value the value of the float + * @return the nan id of float */ public float addFloat(float value) { int id = mRemoteComposeState.cacheFloat(value); - FloatConstant.COMPANION.apply(mBuffer, id, value); + FloatConstant.apply(mBuffer, id, value); return Utils.asNan(id); } /** * Add a Integer return an id number pointing to that float. - * @param value - * @return + * @param value adds an integer and assigns it an id + * @return the id of the integer to be used */ public int addInteger(int value) { int id = mRemoteComposeState.cacheInteger(value); - IntegerConstant.COMPANION.apply(mBuffer, id, value); + IntegerConstant.apply(mBuffer, id, value); return id; } /** * Add a IntegerId as float ID. * @param id id to be converted - * @return + * @return the id wrapped in a NaN */ public float asFloatId(int id) { return Utils.asNan(id); @@ -918,8 +952,8 @@ public class RemoteComposeBuffer { * @return NaN id of the result of the calculation */ public float addAnimatedFloat(float... value) { - int id = mRemoteComposeState.cache(value); - FloatExpression.COMPANION.apply(mBuffer, id, value, null); + int id = mRemoteComposeState.cacheData(value); + FloatExpression.apply(mBuffer, id, value, null); return Utils.asNan(id); } @@ -931,8 +965,80 @@ public class RemoteComposeBuffer { * @return NaN id of the result of the calculation */ public float addAnimatedFloat(float[] value, float[] animation) { - int id = mRemoteComposeState.cache(value); - FloatExpression.COMPANION.apply(mBuffer, id, value, animation); + int id = mRemoteComposeState.cacheData(value); + FloatExpression.apply(mBuffer, id, value, animation); + return Utils.asNan(id); + } + + + /** + * add a float array + * + * @param values + * + * @return the id of the array, encoded as a float NaN + */ + public float addFloatArray(float[] values) { + int id = mRemoteComposeState.cacheData(values, NanMap.TYPE_ARRAY); + DataListFloat.apply(mBuffer, id, values); + return Utils.asNan(id); + } + + /** + * This creates a list of individual floats + * @param values array of floats to be individually stored + * + * @return id of the list + */ + public float addFloatList(float[] values) { + int []listId = new int[values.length]; + for (int i = 0; i < listId.length; i++) { + listId[i] = mRemoteComposeState.cacheFloat(values[i]); + FloatConstant.apply(mBuffer, listId[i], values[i]); + } + return addList(listId); + } + + /** + * This creates a list of individual floats + * @param listId array id to be stored + * + * @return id of the list + */ + public float addList(int[] listId) { + int id = mRemoteComposeState.cacheData(listId, NanMap.TYPE_ARRAY); + DataListIds.apply(mBuffer, id, listId); + return Utils.asNan(id); + } + + /** + * add a float map + * + * @param keys + * @param values + * + * @return the id of the map, encoded as a float NaN + */ + public float addFloatMap(String[]keys, float[] values) { + int []listId = new int[values.length]; + for (int i = 0; i < listId.length; i++) { + listId[i] = mRemoteComposeState.cacheFloat(values[i]); + FloatConstant.apply(mBuffer, listId[i], values[i]); + } + return addMap(keys, listId); + } + + /** + * add an int map + * + * @param keys + * @param listId + * + * @return the id of the map, encoded as a float NaN + */ + public float addMap(String []keys, int[] listId) { + int id = mRemoteComposeState.cacheData(listId, NanMap.TYPE_ARRAY); + DataMapIds.apply(mBuffer, id, keys, listId); return Utils.asNan(id); } @@ -940,22 +1046,22 @@ public class RemoteComposeBuffer { * Add and integer expression * @param mask defines which elements are operators or variables * @param value array of values to calculate maximum 32 - * @return + * @return the id as an integer */ public int addIntegerExpression(int mask, int[] value) { - int id = mRemoteComposeState.cache(value); - IntegerExpression.COMPANION.apply(mBuffer, id, mask, value); + int id = mRemoteComposeState.cacheData(value); + IntegerExpression.apply(mBuffer, id, mask, value); return id; } /** * Add a simple color - * @param color + * @param color the RGB color value * @return id that represents that color */ public int addColor(int color) { ColorConstant c = new ColorConstant(0, color); - short id = (short) mRemoteComposeState.cache(c); + short id = (short) mRemoteComposeState.cacheData(c); c.mColorId = id; c.write(mBuffer); return id; @@ -964,14 +1070,14 @@ public class RemoteComposeBuffer { /** * Add a color that represents the tween between two colors - * @param color1 - * @param color2 - * @param tween + * @param color1 the ARGB value of the first color + * @param color2 the ARGB value of the second color + * @param tween the interpolation bet * @return id of the color (color ids are short) */ public short addColorExpression(int color1, int color2, float tween) { ColorExpression c = new ColorExpression(0, 0, color1, color2, tween); - short id = (short) mRemoteComposeState.cache(c); + short id = (short) mRemoteComposeState.cacheData(c); c.mId = id; c.write(mBuffer); return id; @@ -980,14 +1086,14 @@ public class RemoteComposeBuffer { /** * Add a color that represents the tween between two colors where color1 * is the id of a color - * @param color1 - * @param color2 - * @param tween + * @param color1 id of color + * @param color2 rgb color value + * @param tween the tween between color1 and color2 (1 = color2) * @return id of the color (color ids are short) */ public short addColorExpression(short color1, int color2, float tween) { ColorExpression c = new ColorExpression(0, 1, color1, color2, tween); - short id = (short) mRemoteComposeState.cache(c); + short id = (short) mRemoteComposeState.cacheData(c); c.mId = id; c.write(mBuffer); return id; @@ -996,14 +1102,14 @@ public class RemoteComposeBuffer { /** * Add a color that represents the tween between two colors where color2 * is the id of a color - * @param color1 - * @param color2 - * @param tween + * @param color1 the ARGB value of the first color + * @param color2 id of the second color + * @param tween the tween between color1 and color2 (1 = color2) * @return id of the color (color ids are short) */ public short addColorExpression(int color1, short color2, float tween) { ColorExpression c = new ColorExpression(0, 2, color1, color2, tween); - short id = (short) mRemoteComposeState.cache(c); + short id = (short) mRemoteComposeState.cacheData(c); c.mId = id; c.write(mBuffer); return id; @@ -1012,30 +1118,30 @@ public class RemoteComposeBuffer { /** * Add a color that represents the tween between two colors where color1 & * color2 are the ids of colors - * @param color1 - * @param color2 - * @param tween + * @param color1 id of the first color + * @param color2 id of the second color + * @param tween the tween between color1 and color2 (1 = color2) * @return id of the color (color ids are short) */ public short addColorExpression(short color1, short color2, float tween) { ColorExpression c = new ColorExpression(0, 3, color1, color2, tween); - short id = (short) mRemoteComposeState.cache(c); + short id = (short) mRemoteComposeState.cacheData(c); c.mId = id; c.write(mBuffer); return id; } /** - * Color calculated by Hue saturation and value. - * (as floats they can be variables used to create color transitions) - * @param hue - * @param sat - * @param value + * Color calculated by Hue saturation and value. + * (as floats they can be variables used to create color transitions) + * @param hue the Hue + * @param sat the saturation + * @param value the value * @return id of the color (color ids are short) */ public short addColorExpression(float hue, float sat, float value) { ColorExpression c = new ColorExpression(0, hue, sat, value); - short id = (short) mRemoteComposeState.cache(c); + short id = (short) mRemoteComposeState.cacheData(c); c.mId = id; c.write(mBuffer); return id; @@ -1044,15 +1150,15 @@ public class RemoteComposeBuffer { /** * Color calculated by Alpha, Hue saturation and value. * (as floats they can be variables used to create color transitions) - * @param alpha - * @param hue - * @param sat - * @param value + * @param alpha the Alpha + * @param hue the hue + * @param sat the saturation + * @param value the value * @return id of the color (color ids are short) */ public short addColorExpression(int alpha, float hue, float sat, float value) { ColorExpression c = new ColorExpression(0, alpha, hue, sat, value); - short id = (short) mRemoteComposeState.cache(c); + short id = (short) mRemoteComposeState.cacheData(c); c.mId = id; c.write(mBuffer); return id; @@ -1061,11 +1167,11 @@ public class RemoteComposeBuffer { /** * create and animation based on description and return as an array of * floats. see addAnimatedFloat - * @param duration - * @param type - * @param spec - * @param initialValue - * @param wrap + * @param duration the duration of the aimation + * @param type the type of animation + * @param spec the parameters of the animation if any + * @param initialValue the initial value if it animates to a start + * @param wrap the wraps value so (e.g 360 so angles 355 would animate to 5) * @return */ public static float[] packAnimation(float duration, @@ -1083,39 +1189,49 @@ public class RemoteComposeBuffer { * @param name Name of the color */ public void setColorName(int id, String name) { - NamedVariable.COMPANION.apply(mBuffer, id, + NamedVariable.apply(mBuffer, id, NamedVariable.COLOR_TYPE, name); } /** + * This defines the name of the string given the id + * + * @param id of the string + * @param name name of the string + */ + public void setStringName(int id, String name) { + NamedVariable.apply(mBuffer, id, + NamedVariable.STRING_TYPE, name); + } + + /** + * Returns a usable component id -- either the one passed in parameter if not -1 + * or a generated one. + * + * @param id the current component id (if -1, we'll generate a new one) + * + * @return a usable component id + */ + private int getComponentId(int id) { + int resolvedId = 0; + if (id != -1) { + resolvedId = id; + } else { + mGeneratedComponentId--; + resolvedId = mGeneratedComponentId; + } + return resolvedId; + } + + /** * Add a component start tag * @param type type of component * @param id component id */ public void addComponentStart(int type, int id) { - switch (type) { - case ComponentStart.ROOT_LAYOUT: { - RootLayoutComponent.COMPANION.apply(mBuffer); - } break; - case ComponentStart.LAYOUT_CONTENT: { - LayoutComponentContent.COMPANION.apply(mBuffer); - } break; - case ComponentStart.LAYOUT_BOX: { - BoxLayout.COMPANION.apply(mBuffer, id, -1, - BoxLayout.CENTER, BoxLayout.CENTER); - } break; - case ComponentStart.LAYOUT_ROW: { - RowLayout.COMPANION.apply(mBuffer, id, -1, - RowLayout.START, RowLayout.TOP, 0f); - } break; - case ComponentStart.LAYOUT_COLUMN: { - ColumnLayout.COMPANION.apply(mBuffer, id, -1, - ColumnLayout.START, ColumnLayout.TOP, 0f); - } break; - default: - ComponentStart.Companion.apply(mBuffer, - type, id, 0f, 0f); - } + mLastComponentId = getComponentId(id); + ComponentStart.apply(mBuffer, + type, mLastComponentId, 0f, 0f); } /** @@ -1130,7 +1246,7 @@ public class RemoteComposeBuffer { * Add a component end tag */ public void addComponentEnd() { - ComponentEnd.Companion.apply(mBuffer); + ComponentEnd.apply(mBuffer); } /** @@ -1143,7 +1259,7 @@ public class RemoteComposeBuffer { float g = ((color >> 8) & 0xff) / 255.0f; float b = ((color) & 0xff) / 255.0f; float a = ((color >> 24) & 0xff) / 255.0f; - BackgroundModifierOperation.COMPANION.apply(mBuffer, 0f, 0f, 0f, 0f, + BackgroundModifierOperation.apply(mBuffer, 0f, 0f, 0f, 0f, r, g, b, a, shape); } @@ -1160,7 +1276,7 @@ public class RemoteComposeBuffer { float g = ((color >> 8) & 0xff) / 255.0f; float b = ((color) & 0xff) / 255.0f; float a = ((color >> 24) & 0xff) / 255.0f; - BorderModifierOperation.COMPANION.apply(mBuffer, 0f, 0f, 0f, 0f, + BorderModifierOperation.apply(mBuffer, 0f, 0f, 0f, 0f, borderWidth, borderRoundedCorner, r, g, b, a, shape); } @@ -1172,10 +1288,9 @@ public class RemoteComposeBuffer { * @param bottom bottom padding */ public void addModifierPadding(float left, float top, float right, float bottom) { - PaddingModifierOperation.COMPANION.apply(mBuffer, left, top, right, bottom); + PaddingModifierOperation.apply(mBuffer, left, top, right, bottom); } - /** * Sets the clip based on rounded clip rect * @param topStart @@ -1185,30 +1300,138 @@ public class RemoteComposeBuffer { */ public void addRoundClipRectModifier(float topStart, float topEnd, float bottomStart, float bottomEnd) { - RoundedClipRectModifierOperation.COMPANION.apply(mBuffer, + RoundedClipRectModifierOperation.apply(mBuffer, topStart, topEnd, bottomStart, bottomEnd); } + /** + * Add a clip rect modifier + */ public void addClipRectModifier() { - ClipRectModifierOperation.COMPANION.apply(mBuffer); + ClipRectModifierOperation.apply(mBuffer); } + /** + * Add a box start tag + * + * @param componentId component id + * @param animationId animation id + * @param horizontal horizontal alignment + * @param vertical vertical alignment + */ public void addBoxStart(int componentId, int animationId, int horizontal, int vertical) { - BoxLayout.COMPANION.apply(mBuffer, componentId, animationId, + mLastComponentId = getComponentId(componentId); + BoxLayout.apply(mBuffer, mLastComponentId, animationId, horizontal, vertical); } + /** + * Add a row start tag + * + * @param componentId component id + * @param animationId animation id + * @param horizontal horizontal alignment + * @param vertical vertical alignment + * @param spacedBy spacing between items + */ public void addRowStart(int componentId, int animationId, int horizontal, int vertical, float spacedBy) { - RowLayout.COMPANION.apply(mBuffer, componentId, animationId, + mLastComponentId = getComponentId(componentId); + RowLayout.apply(mBuffer, mLastComponentId, animationId, horizontal, vertical, spacedBy); } + /** + * Add a column start tag + * + * @param componentId component id + * @param animationId animation id + * @param horizontal horizontal alignment + * @param vertical vertical alignment + * @param spacedBy spacing between items + */ public void addColumnStart(int componentId, int animationId, int horizontal, int vertical, float spacedBy) { - ColumnLayout.COMPANION.apply(mBuffer, componentId, animationId, + mLastComponentId = getComponentId(componentId); + ColumnLayout.apply(mBuffer, mLastComponentId, animationId, horizontal, vertical, spacedBy); } + + /** + * Add a canvas start tag + * @param componentId component id + * @param animationId animation id + */ + public void addCanvasStart(int componentId, int animationId) { + mLastComponentId = getComponentId(componentId); + CanvasLayout.apply(mBuffer, mLastComponentId, animationId); + } + + /** + * Add a canvas content start tag + * @param componentId component id + */ + public void addCanvasContentStart(int componentId) { + mLastComponentId = getComponentId(componentId); + CanvasContent.apply(mBuffer, mLastComponentId); + } + + /** + * Add a root start tag + */ + public void addRootStart() { + mLastComponentId = getComponentId(-1); + RootLayoutComponent.apply(mBuffer, mLastComponentId); + } + + /** + * Add a content start tag + */ + public void addContentStart() { + mLastComponentId = getComponentId(-1); + LayoutComponentContent.apply(mBuffer, mLastComponentId); + } + + /** + * Add a component width value + * @param id id of the value + */ + public void addComponentWidthValue(int id) { + ComponentValue.apply(mBuffer, ComponentValue.WIDTH, mLastComponentId, id); + } + + /** + * Add a component height value + * + * @param id id of the value + */ + public void addComponentHeightValue(int id) { + ComponentValue.apply(mBuffer, ComponentValue.HEIGHT, mLastComponentId, id); + } + + /** + * Add a text component start tag + * + * @param componentId component id + * @param animationId animation id + * @param textId id of the text + * @param color color of the text + * @param fontSize font size + * @param fontStyle font style (0 : Normal, 1 : Italic) + * @param fontWeight font weight (1 to 1000, normal is 400) + * @param fontFamily font family or null + */ + public void addTextComponentStart(int componentId, int animationId, + int textId, int color, float fontSize, + int fontStyle, float fontWeight, String fontFamily) { + mLastComponentId = getComponentId(componentId); + int fontFamilyId = -1; + if (fontFamily != null) { + fontFamilyId = addText(fontFamily); + } + TextLayout.apply(mBuffer, mLastComponentId, animationId, textId, color, fontSize, + fontStyle, fontWeight, fontFamilyId); + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeState.java b/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeState.java index 6b06a544be40..839522e29fdb 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeState.java +++ b/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeState.java @@ -20,7 +20,11 @@ import static com.android.internal.widget.remotecompose.core.RemoteContext.ID_TI import static com.android.internal.widget.remotecompose.core.RemoteContext.ID_TIME_IN_SEC; import static com.android.internal.widget.remotecompose.core.RemoteContext.ID_WINDOW_HEIGHT; import static com.android.internal.widget.remotecompose.core.RemoteContext.ID_WINDOW_WIDTH; +import static com.android.internal.widget.remotecompose.core.operations.utilities.NanMap.START_ARRAY; +import static com.android.internal.widget.remotecompose.core.operations.utilities.NanMap.START_VAR; +import com.android.internal.widget.remotecompose.core.operations.utilities.ArrayAccess; +import com.android.internal.widget.remotecompose.core.operations.utilities.CollectionsAccess; import com.android.internal.widget.remotecompose.core.operations.utilities.IntFloatMap; import com.android.internal.widget.remotecompose.core.operations.utilities.IntIntMap; import com.android.internal.widget.remotecompose.core.operations.utilities.IntMap; @@ -32,18 +36,28 @@ import java.util.HashMap; * Represents runtime state for a RemoteCompose document * State includes things like the value of variables */ -public class RemoteComposeState { +public class RemoteComposeState implements CollectionsAccess { public static final int START_ID = 42; private static final int MAX_FLOATS = 500; private static final int MAX_COLORS = 200; + + private static final int MAX_DATA = 1000; private final IntMap<Object> mIntDataMap = new IntMap<>(); private final IntMap<Boolean> mIntWrittenMap = new IntMap<>(); - private final HashMap<Object, Integer> mDataIntMap = new HashMap(); + private final HashMap<Object, Integer> mDataIntMap = new HashMap<>(); private final IntFloatMap mFloatMap = new IntFloatMap(); // efficient cache private final IntIntMap mIntegerMap = new IntIntMap(); // efficient cache private final IntIntMap mColorMap = new IntIntMap(); // efficient cache + private final boolean[] mColorOverride = new boolean[MAX_COLORS]; + private final IntMap<ArrayAccess> mCollectionMap = new IntMap<>(); + + private final boolean[] mDataOverride = new boolean[MAX_DATA]; + private final boolean[] mIntegerOverride = new boolean[MAX_DATA]; + private int mNextId = START_ID; + private int[] mIdMaps = new int[]{START_ID, START_VAR, START_ARRAY}; + private RemoteContext mRemoteContext = null; /** @@ -70,8 +84,8 @@ public class RemoteComposeState { /** * Return the id of an item from the cache. */ - public int dataGetId(Object image) { - Integer res = mDataIntMap.get(image); + public int dataGetId(Object data) { + Integer res = mDataIntMap.get(data); if (res == null) { return -1; } @@ -79,29 +93,31 @@ public class RemoteComposeState { } /** - * Add an image to the cache. Generates an id for the image and adds it to the cache based on + * Add an item to the cache. Generates an id for the item and adds it to the cache based on * that id. */ - public int cache(Object image) { + public int cacheData(Object item) { int id = nextId(); - mDataIntMap.put(image, id); - mIntDataMap.put(id, image); + mDataIntMap.put(item, id); + mIntDataMap.put(id, item); return id; } /** - * Insert an item in the cache + * Add an item to the cache. Generates an id for the item and adds it to the cache based on + * that id. */ - public void cache(int id, Object item) { + public int cacheData(Object item, int type) { + int id = nextId(type); mDataIntMap.put(item, id); mIntDataMap.put(id, item); + return id; } /** * Insert an item in the cache */ - public void update(int id, Object item) { - mDataIntMap.remove(mIntDataMap.get(id)); + public void cacheData(int id, Object item) { mDataIntMap.put(item, id); mIntDataMap.put(id, item); } @@ -109,20 +125,36 @@ public class RemoteComposeState { /** * Insert an item in the cache */ - public int cacheFloat(float item) { - int id = nextId(); - mFloatMap.put(id, item); - mIntegerMap.put(id, (int) item); - return id; + public void updateData(int id, Object item) { + if (!mDataOverride[id]) { + mDataIntMap.remove(mIntDataMap.get(id)); + mDataIntMap.put(item, id); + mIntDataMap.put(id, item); + updateListeners(id); + } + } + + /** + * Adds a data Override. + * + * @param id + * @param item the new value + */ + public void overrideData(int id, Object item) { + mDataIntMap.remove(mIntDataMap.get(id)); + mDataIntMap.put(item, id); + mIntDataMap.put(id, item); + mDataOverride[id] = true; + updateListeners(id); } /** * Insert an item in the cache */ - public int cacheInteger(int item) { + public int cacheFloat(float item) { int id = nextId(); - mIntegerMap.put(id, item); mFloatMap.put(id, item); + mIntegerMap.put(id, (int) item); return id; } @@ -139,14 +171,41 @@ public class RemoteComposeState { public void updateFloat(int id, float item) { mFloatMap.put(id, item); mIntegerMap.put(id, (int) item); + updateListeners(id); + } + + /** + * Insert an item in the cache + */ + public int cacheInteger(int item) { + int id = nextId(); + mIntegerMap.put(id, item); + mFloatMap.put(id, item); + return id; } /** * Insert an integer item in the cache */ public void updateInteger(int id, int item) { - mFloatMap.put(id, item); - mIntegerMap.put(id, item); + if (!mIntegerOverride[id]) { + mFloatMap.put(id, item); + mIntegerMap.put(id, item); + updateListeners(id); + } + } + + /** + * Adds a integer Override. + * + * @param id + * @param value the new value + */ + public void overrideInteger(int id, int value) { + mIntegerMap.put(id, value); + mFloatMap.put(id, value); + mIntegerOverride[id] = true; + updateListeners(id); } /** @@ -190,11 +249,21 @@ public class RemoteComposeState { return; } mColorMap.put(id, color); + updateListeners(id); + } + + private void updateListeners(int id) { + ArrayList<VariableSupport> v = mVarListeners.get(id); + if (v != null && mRemoteContext != null) { + for (VariableSupport c : v) { + c.updateVariables(mRemoteContext); + } + } } /** * Adds a colorOverride. - * This is a list of ids and there colors optimized for playback; + * This is a list of ids and their colors optimized for playback; * * @param id * @param color @@ -214,6 +283,26 @@ public class RemoteComposeState { } /** + * Clear the data override + * + * @param id the data id to clear + */ + public void clearDataOverride(int id) { + mDataOverride[id] = false; + updateListeners(id); + } + + /** + * Clear the integer override + * + * @param id the integer id to clear + */ + public void clearIntegerOverride(int id) { + mIntegerOverride[id] = false; + updateListeners(id); + } + + /** * Method to determine if a cached value has been written to the documents WireBuffer based on * its id. */ @@ -231,8 +320,9 @@ public class RemoteComposeState { /** * Clear the record of the values that have been written to the WireBuffer. */ - void reset() { + public void reset() { mIntWrittenMap.clear(); + mDataIntMap.clear(); } /** @@ -245,6 +335,18 @@ public class RemoteComposeState { } /** + * Get the next available id + * + * @return + */ + public int nextId(int type) { + if (0 == type) { + return mNextId++; + } + return mIdMaps[type]++; + } + + /** * Set the next id * * @param id @@ -316,4 +418,25 @@ public class RemoteComposeState { updateFloat(ID_WINDOW_HEIGHT, height); } + public void addCollection(int id, ArrayAccess collection) { + mCollectionMap.put(id & 0xFFFFF, collection); + } + + @Override + public float getFloatValue(int id, int index) { + return mCollectionMap.get(id & 0xFFFFF).getFloatValue(index); + } + @Override + public float[] getFloats(int id) { + return mCollectionMap.get(id & 0xFFFFF).getFloats(); + } + + @Override + public int getFloatsLength(int id) { + return mCollectionMap.get(id & 0xFFFFF).getFloatsLength(); + } + + public void setContext(RemoteContext context) { + mRemoteContext = context; + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/RemoteContext.java b/core/java/com/android/internal/widget/remotecompose/core/RemoteContext.java index 893dcce30842..0df0aa04ec9c 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/RemoteContext.java +++ b/core/java/com/android/internal/widget/remotecompose/core/RemoteContext.java @@ -20,6 +20,13 @@ import com.android.internal.widget.remotecompose.core.operations.ShaderData; import com.android.internal.widget.remotecompose.core.operations.Theme; import com.android.internal.widget.remotecompose.core.operations.Utils; import com.android.internal.widget.remotecompose.core.operations.layout.Component; +import com.android.internal.widget.remotecompose.core.operations.utilities.ArrayAccess; +import com.android.internal.widget.remotecompose.core.operations.utilities.CollectionsAccess; + +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.time.ZoneId; +import java.time.ZoneOffset; /** * Specify an abstract context used to playback RemoteCompose documents @@ -57,8 +64,18 @@ public abstract class RemoteContext { } /** + * Provide access to the table of collections + * + * @return the CollectionsAccess implementation + */ + public CollectionsAccess getCollectionsAccess() { + return mRemoteComposeState; + } + + /** * Load a path under an id. * Paths can be use in clip drawPath and drawTweenPath + * * @param instanceId * @param floatPath */ @@ -67,22 +84,24 @@ public abstract class RemoteContext { /** * Associate a name with a give id. * - * @param varName - * @param varId - * @param varType + * @param varName the name + * @param varId the id (color,integer,float etc.) + * @param varType thetype */ public abstract void loadVariableName(String varName, int varId, int varType); /** * Save a color under a given id - * @param id - * @param color + * + * @param id the id of the color + * @param color the color to set */ public abstract void loadColor(int id, int color); /** * Set the animation time allowing the creator to control animation rates - * @param time + * + * @param time the animation time in seconds */ public void setAnimationTime(float time) { mAnimationTime = time; @@ -90,6 +109,7 @@ public abstract class RemoteContext { /** * gets the time animation clock as float in seconds + * * @return a monotonic time in seconds (arbitrary zero point) */ public float getAnimationTime() { @@ -100,11 +120,60 @@ public abstract class RemoteContext { /** * Set the value of a named Color. * This overrides the color in the document - * @param colorName - * @param color + * + * @param colorName the name of the color to override + * @param color Override the default color */ public abstract void setNamedColorOverride(String colorName, int color); + /** + * Set the value of a named String. + * This overrides the string in the document + * @param stringName the name of the string to override + * @param value Override the default string + */ + public abstract void setNamedStringOverride(String stringName, String value); + + + /** + * Allows to clear a named String. + * + * If an override exists, we revert back to the default value in the document. + * + * @param stringName the name of the string to override + */ + public abstract void clearNamedStringOverride(String stringName); + + /** + * Set the value of a named Integer. + * This overrides the integer in the document + * @param integerName the name of the integer to override + * @param value Override the default integer + */ + public abstract void setNamedIntegerOverride(String integerName, int value); + + /** + * Allows to clear a named Integer. + * + * If an override exists, we revert back to the default value in the document. + * + * @param integerName the name of the integer to override + */ + public abstract void clearNamedIntegerOverride(String integerName); + + + /** + * Support Collections by registering this collection + * + * @param id id of the collection + * @param collection the collection under this id + */ + public abstract void addCollection(int id, ArrayAccess collection); + + public abstract void runAction(int id, String metadata); + + public abstract void runNamedAction(int textId); + /** * The context can be used in a few different mode, allowing operations to skip being executed: @@ -112,7 +181,7 @@ public abstract class RemoteContext { * - DATA : only operations dealing with DATA (eg loading a bitmap) should execute * - PAINT : only operations painting should execute */ - public enum ContextMode { + public enum ContextMode { UNSET, DATA, PAINT } @@ -174,21 +243,21 @@ public abstract class RemoteContext { /** * Sets the way the player handles the content * - * @param scroll set the horizontal behavior (NONE|SCROLL_HORIZONTAL|SCROLL_VERTICAL) + * @param scroll set the horizontal behavior (NONE|SCROLL_HORIZONTAL|SCROLL_VERTICAL) * @param alignment set the alignment of the content (TOP|CENTER|BOTTOM|START|END) - * @param sizing set the type of sizing for the content (NONE|SIZING_LAYOUT|SIZING_SCALE) - * @param mode set the mode of sizing, either LAYOUT modes or SCALE modes - * the LAYOUT modes are: - * - LAYOUT_MATCH_PARENT - * - LAYOUT_WRAP_CONTENT - * or adding an horizontal mode and a vertical mode: - * - LAYOUT_HORIZONTAL_MATCH_PARENT - * - LAYOUT_HORIZONTAL_WRAP_CONTENT - * - LAYOUT_HORIZONTAL_FIXED - * - LAYOUT_VERTICAL_MATCH_PARENT - * - LAYOUT_VERTICAL_WRAP_CONTENT - * - LAYOUT_VERTICAL_FIXED - * The LAYOUT_*_FIXED modes will use the intrinsic document size + * @param sizing set the type of sizing for the content (NONE|SIZING_LAYOUT|SIZING_SCALE) + * @param mode set the mode of sizing, either LAYOUT modes or SCALE modes + * the LAYOUT modes are: + * - LAYOUT_MATCH_PARENT + * - LAYOUT_WRAP_CONTENT + * or adding an horizontal mode and a vertical mode: + * - LAYOUT_HORIZONTAL_MATCH_PARENT + * - LAYOUT_HORIZONTAL_WRAP_CONTENT + * - LAYOUT_HORIZONTAL_FIXED + * - LAYOUT_VERTICAL_MATCH_PARENT + * - LAYOUT_VERTICAL_WRAP_CONTENT + * - LAYOUT_VERTICAL_FIXED + * The LAYOUT_*_FIXED modes will use the intrinsic document size */ public void setRootContentBehavior(int scroll, int alignment, int sizing, int mode) { mDocument.setRootContentBehavior(scroll, alignment, sizing, mode); @@ -196,6 +265,7 @@ public abstract class RemoteContext { /** * Set a content description for the document + * * @param contentDescriptionId the text id pointing at the description */ public void setDocumentContentDescription(int contentDescriptionId) { @@ -209,94 +279,112 @@ public abstract class RemoteContext { /** * Save a bitmap under an imageId - * @param imageId - * @param width - * @param height - * @param bitmap + * + * @param imageId the id of the image + * @param width the width of the image + * @param height the height of the image + * @param bitmap the bytes that represent the image */ public abstract void loadBitmap(int imageId, int width, int height, byte[] bitmap); /** * Save a string under a given id - * @param id - * @param text + * + * @param id the id of the string + * @param text the value to set */ public abstract void loadText(int id, String text); /** * Get a string given an id - * @param id + * + * @param id the id of the string * @return */ public abstract String getText(int id); /** * Load a float - * @param id - * @param value + * + * @param id id of the float + * @param value the value to set */ public abstract void loadFloat(int id, float value); /** - * Load a float - * @param id - * @param value + * Load a integer + * + * @param id id of the integer + * @param value the value to set */ public abstract void loadInteger(int id, int value); + + public abstract void overrideInteger(int id, int value); + + public abstract void overrideText(int id, int valueId); + /** * Load an animated float associated with an id * Todo: Remove? - * @param id - * @param animatedFloat + * + * @param id the id of the float + * @param animatedFloat The animated float */ public abstract void loadAnimatedFloat(int id, FloatExpression animatedFloat); /** * Save a shader under and ID - * @param id - * @param value + * + * @param id the id of the Shader + * @param value the shader */ public abstract void loadShader(int id, ShaderData value); /** * Get a float given an id - * @param id - * @return + * + * @param id the id of the float + * @return the value of the float */ public abstract float getFloat(int id); /** - * Get a float given an id - * @param id - * @return + * Get a Integer given an id + * + * @param id of the integer + * @return the value */ public abstract int getInteger(int id); /** * Get the color given and ID - * @param id - * @return + * + * @param id of the color + * @return the color */ public abstract int getColor(int id); /** * called to notify system that a command is interested in a variable - * @param id - * @param variableSupport + * + * @param id track when this id changes value + * @param variableSupport call back when value changes */ public abstract void listensTo(int id, VariableSupport variableSupport); /** * Notify commands with variables have changed - * @return + * + * @return the number of ms to next update */ public abstract int updateOps(); /** * Get a shader given the id - * @param id - * @return + * + * @param id get a shader given the id + * @return The shader */ public abstract ShaderData getShader(int id); @@ -352,6 +440,55 @@ public abstract class RemoteContext { /////////////////////////////////////////////////////////////////////////////////////////////// // Click handling /////////////////////////////////////////////////////////////////////////////////////////////// + public static boolean isTime(float fl) { + int value = Utils.idFromNan(fl); + return value >= ID_CONTINUOUS_SEC && value <= ID_DAY_OF_MONTH; + } + + public static float getTime(float fl) { + LocalDateTime dateTime = LocalDateTime.now(); + // This define the time in the format + // seconds run from Midnight=0 quantized to seconds hour 0..3599 + // minutes run from Midnight=0 quantized to minutes 0..1439 + // hours run from Midnight=0 quantized to Hours 0-23 + // CONTINUOUS_SEC is seconds from midnight looping every hour 0-3600 + // CONTINUOUS_SEC is accurate to milliseconds due to float precession + // ID_OFFSET_TO_UTC is the offset from UTC in sec (typically / 3600f) + int value = Utils.idFromNan(fl); + int month = dateTime.getMonth().getValue(); + int hour = dateTime.getHour(); + int minute = dateTime.getMinute(); + int seconds = dateTime.getSecond(); + int currentMinute = hour * 60 + minute; + int currentSeconds = minute * 60 + seconds; + float sec = currentSeconds + dateTime.getNano() * 1E-9f; + int day_week = dateTime.getDayOfWeek().getValue(); + + + ZoneId zone = ZoneId.systemDefault(); + OffsetDateTime offsetDateTime = dateTime.atZone(zone).toOffsetDateTime(); + ZoneOffset offset = offsetDateTime.getOffset(); + switch (value) { + case ID_OFFSET_TO_UTC: + return offset.getTotalSeconds(); + case ID_CONTINUOUS_SEC: + return sec; + case ID_TIME_IN_SEC: + return currentSeconds; + case ID_TIME_IN_MIN: + return currentMinute; + case ID_TIME_IN_HR: + return hour; + case ID_CALENDAR_MONTH: + case ID_DAY_OF_MONTH: + return month; + case ID_WEEK_DAY: + return day_week; + } + return fl; + } + + public abstract void addClickArea( int id, diff --git a/core/java/com/android/internal/widget/remotecompose/core/SerializableToString.java b/core/java/com/android/internal/widget/remotecompose/core/SerializableToString.java new file mode 100644 index 000000000000..8f9741dd4195 --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/SerializableToString.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget.remotecompose.core; + +import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer; + +public interface SerializableToString { + void serializeToString(int indent, StringSerializer serializer); +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/VariableSupport.java b/core/java/com/android/internal/widget/remotecompose/core/VariableSupport.java index d59b1bc65256..ee6d5798bdb2 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/VariableSupport.java +++ b/core/java/com/android/internal/widget/remotecompose/core/VariableSupport.java @@ -17,7 +17,7 @@ package com.android.internal.widget.remotecompose.core; /** * Interface for operators that interact with variables - * Threw this they register to listen to particular variables + * Through this they register to listen to particular variables * and are notified when they change */ public interface VariableSupport { diff --git a/core/java/com/android/internal/widget/remotecompose/core/documentation/DocumentedCompanionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/documentation/DocumentedCompanionOperation.java index 6a98b78f569d..4b84291aa5fe 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/documentation/DocumentedCompanionOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/documentation/DocumentedCompanionOperation.java @@ -15,8 +15,6 @@ */ package com.android.internal.widget.remotecompose.core.documentation; -import com.android.internal.widget.remotecompose.core.CompanionOperation; - -public interface DocumentedCompanionOperation extends CompanionOperation { +public interface DocumentedCompanionOperation { void documentation(DocumentationBuilder doc); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/documentation/Operation.java b/core/java/com/android/internal/widget/remotecompose/core/documentation/Operation.java index 643b925ae637..9ccb2be9969a 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/documentation/Operation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/documentation/Operation.java @@ -27,6 +27,10 @@ public class Operation { public static final int BYTE = 6; public static final int VALUE = 7; public static final int LONG = 8; + public static final int SHORT = 9; + + public static final int FLOAT_ARRAY = 10; + public static final int INT_ARRAY = 11; String mCategory; int mId; @@ -38,7 +42,7 @@ public class Operation { ArrayList<StringPair> mExamples = new ArrayList<>(); ArrayList<OperationField> mFields = new ArrayList<>(); - + String mVarSize = ""; int mExamplesWidth = 100; int mExamplesHeight = 100; @@ -53,6 +57,9 @@ public class Operation { case (BYTE): return "BYTE"; case (VALUE): return "VALUE"; case (LONG): return "LONG"; + case (SHORT): return "SHORT"; + case (FLOAT_ARRAY): return "FLOAT[]"; + case (INT_ARRAY): return "INT[]"; } return "UNKNOWN"; } @@ -88,10 +95,18 @@ public class Operation { return mWIP; } + public String getVarSize() { + return mVarSize; + } + public int getSizeFields() { int size = 0; + mVarSize = ""; for (OperationField field : mFields) { - size += field.getSize(); + size += Math.max(0, field.getSize()); + if (field.getSize() < 0) { + mVarSize += " + " + field.getVarSize() + " x 4"; + } } return size; } @@ -121,6 +136,11 @@ public class Operation { return this; } + public Operation field(int type, String name, String varSize, String description) { + mFields.add(new OperationField(type, name, varSize, description)); + return this; + } + public Operation possibleValues(String name, int value) { if (!mFields.isEmpty()) { mFields.get(mFields.size() - 1).possibleValue(name, "" + value); diff --git a/core/java/com/android/internal/widget/remotecompose/core/documentation/OperationField.java b/core/java/com/android/internal/widget/remotecompose/core/documentation/OperationField.java index fc73f4ed63f8..0dd3039f5f4d 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/documentation/OperationField.java +++ b/core/java/com/android/internal/widget/remotecompose/core/documentation/OperationField.java @@ -21,6 +21,8 @@ public class OperationField { int mType; String mName; String mDescription; + String mVarSize = null; + ArrayList<StringPair> mPossibleValues = new ArrayList<>(); public OperationField(int type, String name, String description) { @@ -28,6 +30,14 @@ public class OperationField { mName = name; mDescription = description; } + + public OperationField(int type, String name, String varSize, String description) { + mType = type; + mName = name; + mDescription = description; + mVarSize = varSize; + } + public int getType() { return mType; } @@ -40,18 +50,28 @@ public class OperationField { public ArrayList<StringPair> getPossibleValues() { return mPossibleValues; } + + public void possibleValue(String name, String value) { mPossibleValues.add(new StringPair(name, value)); } public boolean hasEnumeratedValues() { return !mPossibleValues.isEmpty(); } + + public String getVarSize() { + return mVarSize; + } + public int getSize() { switch (mType) { case (Operation.BYTE) : return 1; case (Operation.INT) : return 4; case (Operation.FLOAT) : return 4; case (Operation.LONG) : return 8; + case (Operation.SHORT) : return 2; + case (Operation.INT_ARRAY): return -1; + case (Operation.FLOAT_ARRAY): return -1; default : return 0; } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/BitmapData.java b/core/java/com/android/internal/widget/remotecompose/core/operations/BitmapData.java index f1863225b766..58be641f608a 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/BitmapData.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/BitmapData.java @@ -15,11 +15,16 @@ */ package com.android.internal.widget.remotecompose.core.operations; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT_ARRAY; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.RemoteContext; +import com.android.internal.widget.remotecompose.core.SerializableToString; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; +import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer; import java.util.List; @@ -28,15 +33,15 @@ import java.util.List; * On getting an Image during a draw call the bitmap is compressed and saved * in playback the image is decompressed */ -public class BitmapData implements Operation { +public class BitmapData implements Operation, SerializableToString { + private static final int OP_CODE = Operations.DATA_BITMAP; + private static final String CLASS_NAME = "BitmapData"; int mImageId; int mImageWidth; int mImageHeight; byte[] mBitmap; public static final int MAX_IMAGE_DIMENSION = 8000; - public static final Companion COMPANION = new Companion(); - public BitmapData(int imageId, int width, int height, byte[] bitmap) { this.mImageId = imageId; this.mImageWidth = width; @@ -44,9 +49,17 @@ public class BitmapData implements Operation { this.mBitmap = bitmap; } + public int getWidth() { + return mImageWidth; + } + + public int getHeight() { + return mImageHeight; + } + @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mImageId, mImageWidth, mImageHeight, mBitmap); + apply(buffer, mImageId, mImageWidth, mImageHeight, mBitmap); } @Override @@ -54,42 +67,51 @@ public class BitmapData implements Operation { return "BITMAP DATA " + mImageId; } - public static class Companion implements CompanionOperation { - private Companion() { - } - @Override - public String name() { - return "BitmapData"; - } + public static String name() { + return CLASS_NAME; + } - @Override - public int id() { - return Operations.DATA_BITMAP; - } + public static int id() { + return OP_CODE; + } - public void apply(WireBuffer buffer, int imageId, int width, int height, byte[] bitmap) { - buffer.start(Operations.DATA_BITMAP); - buffer.writeInt(imageId); - buffer.writeInt(width); - buffer.writeInt(height); - buffer.writeBuffer(bitmap); - } + public static void apply(WireBuffer buffer, int imageId, int width, int height, byte[] bitmap) { + buffer.start(OP_CODE); + buffer.writeInt(imageId); + buffer.writeInt(width); + buffer.writeInt(height); + buffer.writeBuffer(bitmap); + } - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int imageId = buffer.readInt(); - int width = buffer.readInt(); - int height = buffer.readInt(); - if (width < 1 - || height < 1 - || height > MAX_IMAGE_DIMENSION - || width > MAX_IMAGE_DIMENSION) { - throw new RuntimeException("Dimension of image is invalid " + width + "x" + height); - } - byte[] bitmap = buffer.readBuffer(); - operations.add(new BitmapData(imageId, width, height, bitmap)); + + public static void read(WireBuffer buffer, List<Operation> operations) { + int imageId = buffer.readInt(); + int width = buffer.readInt(); + int height = buffer.readInt(); + if (width < 1 + || height < 1 + || height > MAX_IMAGE_DIMENSION + || width > MAX_IMAGE_DIMENSION) { + throw new RuntimeException("Dimension of image is invalid " + width + "x" + height); } + byte[] bitmap = buffer.readBuffer(); + operations.add(new BitmapData(imageId, width, height, bitmap)); + } + + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Data Operations", + OP_CODE, + CLASS_NAME) + .description("Bitmap data") + .field(INT, "id", "id of bitmap data") + .field(INT, "width", + "width of the image") + .field(INT, "height", + "height of the image") + .field(INT_ARRAY, "values", "length", + "Array of ints"); } @Override @@ -102,4 +124,9 @@ public class BitmapData implements Operation { return indent + toString(); } + public void serializeToString(int indent, StringSerializer serializer) { + serializer.append(indent, CLASS_NAME + + " id " + mImageId + " (" + mImageWidth + "x" + mImageHeight + ")"); + } + } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ClickArea.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ClickArea.java index a3cd1973f647..e72e24a0b85a 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/ClickArea.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ClickArea.java @@ -15,12 +15,14 @@ */ package com.android.internal.widget.remotecompose.core.operations; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.RemoteComposeOperation; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import java.util.List; @@ -28,6 +30,8 @@ import java.util.List; * Add a click area to the document */ public class ClickArea implements RemoteComposeOperation { + private static final int OP_CODE = Operations.CLICK_AREA; + private static final String CLASS_NAME = "ClickArea"; int mId; int mContentDescription; float mLeft; @@ -36,18 +40,16 @@ public class ClickArea implements RemoteComposeOperation { float mBottom; int mMetadata; - public static final Companion COMPANION = new Companion(); - /** * Add a click area to the document * - * @param id the id of the click area, which will be reported in the listener - * callback on the player + * @param id the id of the click area, which will be reported in the listener + * callback on the player * @param contentDescription the content description (used for accessibility, as a textID) - * @param left left coordinate of the area bounds - * @param top top coordinate of the area bounds - * @param right right coordinate of the area bounds - * @param bottom bottom coordinate of the area bounds + * @param left left coordinate of the area bounds + * @param top top coordinate of the area bounds + * @param right right coordinate of the area bounds + * @param bottom bottom coordinate of the area bounds * @param metadata associated metadata, user-provided (as a textID, pointing to a string) */ public ClickArea(int id, int contentDescription, @@ -65,7 +67,7 @@ public class ClickArea implements RemoteComposeOperation { @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mId, mContentDescription, mLeft, mTop, mRight, mBottom, mMetadata); + apply(buffer, mId, mContentDescription, mLeft, mTop, mRight, mBottom, mMetadata); } @Override @@ -89,44 +91,57 @@ public class ClickArea implements RemoteComposeOperation { return indent + toString(); } - public static class Companion implements CompanionOperation { - private Companion() {} + public static String name() { + return CLASS_NAME; + } - @Override - public String name() { - return "ClickArea"; - } - @Override - public int id() { - return Operations.CLICK_AREA; - } + public static int id() { + return OP_CODE; + } - public void apply(WireBuffer buffer, int id, int contentDescription, - float left, float top, float right, float bottom, - int metadata) { - buffer.start(Operations.CLICK_AREA); - buffer.writeInt(id); - buffer.writeInt(contentDescription); - buffer.writeFloat(left); - buffer.writeFloat(top); - buffer.writeFloat(right); - buffer.writeFloat(bottom); - buffer.writeInt(metadata); - } + public static void apply(WireBuffer buffer, int id, int contentDescription, + float left, float top, float right, float bottom, + int metadata) { + buffer.start(OP_CODE); + buffer.writeInt(id); + buffer.writeInt(contentDescription); + buffer.writeFloat(left); + buffer.writeFloat(top); + buffer.writeFloat(right); + buffer.writeFloat(bottom); + buffer.writeInt(metadata); + } - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int id = buffer.readInt(); - int contentDescription = buffer.readInt(); - float left = buffer.readFloat(); - float top = buffer.readFloat(); - float right = buffer.readFloat(); - float bottom = buffer.readFloat(); - int metadata = buffer.readInt(); - ClickArea clickArea = new ClickArea(id, contentDescription, - left, top, right, bottom, metadata); - operations.add(clickArea); - } + + public static void read(WireBuffer buffer, List<Operation> operations) { + int id = buffer.readInt(); + int contentDescription = buffer.readInt(); + float left = buffer.readFloat(); + float top = buffer.readFloat(); + float right = buffer.readFloat(); + float bottom = buffer.readFloat(); + int metadata = buffer.readInt(); + ClickArea clickArea = new ClickArea(id, contentDescription, + left, top, right, bottom, metadata); + operations.add(clickArea); + } + + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Canvas Operations", + OP_CODE, + CLASS_NAME) + .description("Define a region you can click on") + .field(FLOAT, "left", + "The left side of the region") + .field(FLOAT, "top", + "The top of the region") + .field(FLOAT, "right", + "The right side of the region") + .field(FLOAT, "bottom", + "The bottom of the region") + .field(FLOAT, "metadata", + "user defined string accessible in callback"); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ClipPath.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ClipPath.java index e6d5fe7043fd..d77d53cca963 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/ClipPath.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ClipPath.java @@ -15,12 +15,14 @@ */ package com.android.internal.widget.remotecompose.core.operations; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; import com.android.internal.widget.remotecompose.core.PaintOperation; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import java.util.List; @@ -30,7 +32,8 @@ import java.util.List; * TODO allow id 0 to mean null? */ public class ClipPath extends PaintOperation { - public static final Companion COMPANION = new Companion(); + private static final int OP_CODE = Operations.CLIP_PATH; + private static final String CLASS_NAME = "ClipPath"; int mId; int mRegionOp; @@ -39,17 +42,25 @@ public class ClipPath extends PaintOperation { mRegionOp = regionOp; } - public static final int REPLACE = Companion.PATH_CLIP_REPLACE; - public static final int DIFFERENCE = Companion.PATH_CLIP_DIFFERENCE; - public static final int INTERSECT = Companion.PATH_CLIP_INTERSECT; - public static final int UNION = Companion.PATH_CLIP_UNION; - public static final int XOR = Companion.PATH_CLIP_XOR; - public static final int REVERSE_DIFFERENCE = Companion.PATH_CLIP_REVERSE_DIFFERENCE; - public static final int UNDEFINED = Companion.PATH_CLIP_UNDEFINED; + public static final int PATH_CLIP_REPLACE = 0; + public static final int PATH_CLIP_DIFFERENCE = 1; + public static final int PATH_CLIP_INTERSECT = 2; + public static final int PATH_CLIP_UNION = 3; + public static final int PATH_CLIP_XOR = 4; + public static final int PATH_CLIP_REVERSE_DIFFERENCE = 5; + public static final int PATH_CLIP_UNDEFINED = 6; + + public static final int REPLACE = PATH_CLIP_REPLACE; + public static final int DIFFERENCE = PATH_CLIP_DIFFERENCE; + public static final int INTERSECT = PATH_CLIP_INTERSECT; + public static final int UNION = PATH_CLIP_UNION; + public static final int XOR = PATH_CLIP_XOR; + public static final int REVERSE_DIFFERENCE = PATH_CLIP_REVERSE_DIFFERENCE; + public static final int UNDEFINED = PATH_CLIP_UNDEFINED; @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mId); + apply(buffer, mId); } @Override @@ -57,43 +68,40 @@ public class ClipPath extends PaintOperation { return "ClipPath " + mId + ";"; } - public static class Companion implements CompanionOperation { - public static final int PATH_CLIP_REPLACE = 0; - public static final int PATH_CLIP_DIFFERENCE = 1; - public static final int PATH_CLIP_INTERSECT = 2; - public static final int PATH_CLIP_UNION = 3; - public static final int PATH_CLIP_XOR = 4; - public static final int PATH_CLIP_REVERSE_DIFFERENCE = 5; - public static final int PATH_CLIP_UNDEFINED = 6; - - private Companion() { - } - - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int pack = buffer.readInt(); - int id = pack & 0xFFFFF; - int regionOp = pack >> 24; - ClipPath op = new ClipPath(id, regionOp); - operations.add(op); - } - - @Override - public String name() { - return "ClipPath"; - } - - @Override - public int id() { - return Operations.CLIP_PATH; - } - - public void apply(WireBuffer buffer, int id) { - buffer.start(Operations.CLIP_PATH); - buffer.writeInt(id); - } + + public static void read(WireBuffer buffer, List<Operation> operations) { + int pack = buffer.readInt(); + int id = pack & 0xFFFFF; + int regionOp = pack >> 24; + ClipPath op = new ClipPath(id, regionOp); + operations.add(op); + } + + + public static String name() { + return CLASS_NAME; + } + + + public static int id() { + return OP_CODE; + } + + public static void apply(WireBuffer buffer, int id) { + buffer.start(OP_CODE); + buffer.writeInt(id); } + public static void documentation(DocumentationBuilder doc) { + doc.operation("Canvas Operations", + OP_CODE, + CLASS_NAME) + .description("Intersect the current clip with the path") + .field(INT, "id", + "id of the path"); + } + + @Override public void paint(PaintContext context) { context.clipPath(mId, mRegionOp); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ClipRect.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ClipRect.java index 613ecebf9100..ec9b6fe483c9 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/ClipRect.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ClipRect.java @@ -15,24 +15,61 @@ */ package com.android.internal.widget.remotecompose.core.operations; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; + +import java.util.List; /** * Support clip with a rectangle */ public class ClipRect extends DrawBase4 { - public static final Companion COMPANION = - new Companion(Operations.CLIP_RECT) { - @Override - public Operation construct(float x1, - float y1, - float x2, - float y2) { - return new ClipRect(x1, y1, x2, y2); - } - }; + public static final int OP_CODE = Operations.CLIP_RECT; + public static final String CLASS_NAME = "ClipRect"; + + + public static void read(WireBuffer buffer, List<Operation> operations) { + Maker m = ClipRect::new; + read(m, buffer, operations); + } + + public static int id() { + return OP_CODE; + } + + public static String name() { + return CLASS_NAME; + } + + + protected void write(WireBuffer buffer, + float v1, + float v2, + float v3, + float v4) { + apply(buffer, v1, v2, v3, v4); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Expressions Operations", + OP_CODE, + CLASS_NAME) + .description("Intersect the current clip with rectangle") + .field(FLOAT, "left", + "The left side of the rectangle to intersect with the current clip") + .field(FLOAT, "top", + "The top of the rectangle to intersect with the current clip") + .field(FLOAT, "right", + "The right side of the rectangle to intersect with the current clip") + .field(FLOAT, "bottom", + "The bottom of the rectangle to intersect with the current clip"); + } + public ClipRect( float left, @@ -40,11 +77,28 @@ public class ClipRect extends DrawBase4 { float right, float bottom) { super(left, top, right, bottom); - mName = "ClipRect"; + mName = CLASS_NAME; } @Override public void paint(PaintContext context) { context.clipRect(mX1, mY1, mX2, mY2); } + + /** + * Writes out the clipRect to the buffer + * + * @param buffer buffer to write to + * @param x1 start x of DrawOval + * @param y1 start y of the DrawOval + * @param x2 end x of the DrawOval + * @param y2 end y of the DrawOval + */ + public static void apply(WireBuffer buffer, + float x1, + float y1, + float x2, + float y2) { + write(buffer, OP_CODE, x1, y1, x2, y2); + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ColorConstant.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ColorConstant.java index 15c208f2de61..2562e18b386c 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/ColorConstant.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ColorConstant.java @@ -15,11 +15,13 @@ */ package com.android.internal.widget.remotecompose.core.operations; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import java.util.List; @@ -28,9 +30,10 @@ import java.util.List; * Mainly for colors in theming. */ public class ColorConstant implements Operation { + private static final int OP_CODE = Operations.COLOR_CONSTANT; + private static final String CLASS_NAME = "ColorConstant"; public int mColorId; public int mColor; - public static final Companion COMPANION = new Companion(); public ColorConstant(int colorId, int color) { this.mColorId = colorId; @@ -39,7 +42,7 @@ public class ColorConstant implements Operation { @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mColorId, mColor); + apply(buffer, mColorId, mColor); } @Override @@ -47,39 +50,42 @@ public class ColorConstant implements Operation { return "ColorConstant[" + mColorId + "] = " + Utils.colorInt(mColor) + ""; } - public static class Companion implements CompanionOperation { - private Companion() { - } + public static String name() { + return CLASS_NAME; + } - @Override - public String name() { - return "ColorConstant"; - } + public static int id() { + return OP_CODE; + } - @Override - public int id() { - return Operations.COLOR_CONSTANT; - } + /** + * Writes out the operation to the buffer + * + * @param buffer + * @param colorId + * @param color + */ + public static void apply(WireBuffer buffer, int colorId, int color) { + buffer.start(OP_CODE); + buffer.writeInt(colorId); + buffer.writeInt(color); + } - /** - * Writes out the operation to the buffer - * - * @param buffer - * @param colorId - * @param color - */ - public void apply(WireBuffer buffer, int colorId, int color) { - buffer.start(Operations.COLOR_CONSTANT); - buffer.writeInt(colorId); - buffer.writeInt(color); - } + public static void read(WireBuffer buffer, List<Operation> operations) { + int colorId = buffer.readInt(); + int color = buffer.readInt(); + operations.add(new ColorConstant(colorId, color)); + } - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int colorId = buffer.readInt(); - int color = buffer.readInt(); - operations.add(new ColorConstant(colorId, color)); - } + public static void documentation(DocumentationBuilder doc) { + doc.operation("Expressions Operations", + OP_CODE, + CLASS_NAME) + .description("Define a Color") + .field(INT, "id", + "Id of the color") + .field(INT, "color", + "32 bit ARGB color"); } @Override diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ColorExpression.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ColorExpression.java index 7d28cea35850..96d667465e8f 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/ColorExpression.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ColorExpression.java @@ -15,12 +15,15 @@ */ package com.android.internal.widget.remotecompose.core.operations; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.VariableSupport; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import java.util.List; @@ -34,6 +37,8 @@ import java.util.List; * mMode = 4 H S V mode */ public class ColorExpression implements Operation, VariableSupport { + private static final int OP_CODE = Operations.COLOR_EXPRESSIONS; + private static final String CLASS_NAME = "ColorExpression"; public int mId; int mMode; public int mColor1; @@ -52,8 +57,8 @@ public class ColorExpression implements Operation, VariableSupport { public float mOutTween = 0.0f; public int mOutColor1; public int mOutColor2; - public static final Companion COMPANION = new Companion(); public static final int HSV_MODE = 4; + public ColorExpression(int id, float hue, float sat, float value) { mMode = HSV_MODE; mAlpha = 0xFF; @@ -64,6 +69,7 @@ public class ColorExpression implements Operation, VariableSupport { mColor2 = Float.floatToRawIntBits(sat); mTween = value; } + public ColorExpression(int id, int alpha, float hue, float sat, float value) { mMode = HSV_MODE; mAlpha = alpha; @@ -90,7 +96,6 @@ public class ColorExpression implements Operation, VariableSupport { this.mOutTween = tween; this.mOutColor1 = color1; this.mOutColor2 = color2; - } @Override @@ -163,13 +168,12 @@ public class ColorExpression implements Operation, VariableSupport { context.loadColor(mId, Utils.interpolateColor(mOutColor1, mOutColor2, mOutTween)); } - } @Override public void write(WireBuffer buffer) { int mode = mMode | (mAlpha << 16); - COMPANION.apply(buffer, mId, mode, mColor1, mColor2, mTween); + apply(buffer, mId, mode, mColor1, mColor2, mTween); } @Override @@ -187,51 +191,66 @@ public class ColorExpression implements Operation, VariableSupport { + Utils.floatToString(mTween) + ")"; } - public static class Companion implements CompanionOperation { - private Companion() { - } + public static String name() { + return CLASS_NAME; + } - @Override - public String name() { - return "ColorExpression"; - } - @Override - public int id() { - return Operations.COLOR_EXPRESSIONS; - } + public static int id() { + return OP_CODE; + } - /** - * Call to write a ColorExpression object on the buffer - * @param buffer - * @param id of the ColorExpression object - * @param mode if colors are id or actual values - * @param color1 - * @param color2 - * @param tween - */ - public void apply(WireBuffer buffer, - int id, int mode, - int color1, int color2, float tween) { - buffer.start(Operations.COLOR_EXPRESSIONS); - buffer.writeInt(id); - buffer.writeInt(mode); - buffer.writeInt(color1); - buffer.writeInt(color2); - buffer.writeFloat(tween); + /** + * Call to write a ColorExpression object on the buffer + * + * @param buffer + * @param id of the ColorExpression object + * @param mode if colors are id or actual values + * @param color1 + * @param color2 + * @param tween + */ + public static void apply(WireBuffer buffer, + int id, int mode, + int color1, int color2, float tween) { + buffer.start(OP_CODE); + buffer.writeInt(id); + buffer.writeInt(mode); + buffer.writeInt(color1); + buffer.writeInt(color2); + buffer.writeFloat(tween); - } + } - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int id = buffer.readInt(); - int mode = buffer.readInt(); - int color1 = buffer.readInt(); - int color2 = buffer.readInt(); - float tween = buffer.readFloat(); + public static void read(WireBuffer buffer, List<Operation> operations) { + int id = buffer.readInt(); + int mode = buffer.readInt(); + int color1 = buffer.readInt(); + int color2 = buffer.readInt(); + float tween = buffer.readFloat(); + + operations.add(new ColorExpression(id, mode, color1, color2, tween)); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Expressions Operations", + OP_CODE, + CLASS_NAME) + .description("A Color defined by an expression") + .field(INT, "id", "Id of the color") + .field(INT, "mode", "The use of the next 3 fields") + .possibleValues("COLOR_COLOR_INTERPOLATE", 0) + .possibleValues("COLOR_ID_INTERPOLATE", 1) + .possibleValues("ID_COLOR_INTERPOLATE", 2) + .possibleValues("ID_ID_INTERPOLATE", 3) + .possibleValues("HSV", 4) + .field(INT, "color1", + "32 bit ARGB color") + .field(INT, "color2", + "32 bit ARGB color") + .field(FLOAT, "tween", + "32 bit ARGB color"); - operations.add(new ColorExpression(id, mode, color1, color2, tween)); - } } @Override diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ComponentValue.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ComponentValue.java new file mode 100644 index 000000000000..22fe673bc072 --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ComponentValue.java @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget.remotecompose.core.operations; + +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; + +import com.android.internal.widget.remotecompose.core.Operation; +import com.android.internal.widget.remotecompose.core.Operations; +import com.android.internal.widget.remotecompose.core.RemoteContext; +import com.android.internal.widget.remotecompose.core.SerializableToString; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; +import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer; + +import java.util.List; + +public class ComponentValue implements Operation, SerializableToString { + public static final int OP_CODE = Operations.COMPONENT_VALUE; + public static final String CLASS_NAME = "ComponentValue"; + + public static final int WIDTH = 0; + public static final int HEIGHT = 1; + + private int mType = WIDTH; + private int mComponentID = -1; + private int mValueId = -1; + + public static int id() { + return OP_CODE; + } + + public static String name() { + return CLASS_NAME; + } + + @Override + public String toString() { + return CLASS_NAME + "(" + mType + ", " + mComponentID + ", " + mValueId + ")"; + } + + public int getType() { + return mType; + } + + public int getComponentId() { + return mComponentID; + } + + public int getValueId() { + return mValueId; + } + + @Override + public void write(WireBuffer buffer) { + apply(buffer, mType, mComponentID, mValueId); + } + + @Override + public void apply(RemoteContext context) { + // Nothing + } + + public static void read(WireBuffer buffer, List<Operation> operations) { + int type = buffer.readInt(); + int componentId = buffer.readInt(); + int valueId = buffer.readInt(); + ComponentValue op = new ComponentValue(type, componentId, valueId); + operations.add(op); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Expressions Operations", + OP_CODE, + CLASS_NAME) + .description("Encode a component-related value (eg its width, height etc.)") + .field(INT, "TYPE", + "The type of value, either WIDTH(0) or HEIGHT(1)") + .field(INT, "COMPONENT_ID", + "The component id to reference") + .field(INT, "VALUE_ID", + "The id of the RemoteFloat representing the described" + + " component value, which can be used in expressions"); + } + + public ComponentValue(int type, int componentId, int valueId) { + mType = type; + mComponentID = componentId; + mValueId = valueId; + } + + /** + * Writes out the ComponentValue to the buffer + * + * @param buffer buffer to write to + * @param type type of value (WIDTH or HEIGHT) + * @param componentId component id to reference + * @param valueId remote float used to represent the component value + */ + public static void apply(WireBuffer buffer, + int type, + int componentId, + int valueId) { + buffer.start(OP_CODE); + buffer.writeInt(type); + buffer.writeInt(componentId); + buffer.writeInt(valueId); + } + + @Override + public String deepToString(String indent) { + return null; + } + + public void serializeToString(int indent, StringSerializer serializer) { + String type = "WIDTH"; + if (mType == HEIGHT) { + type = "HEIGHT"; + } + serializer.append(indent, CLASS_NAME + + " value " + mValueId + " set to " + + type + " of Component " + mComponentID); + } +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DataListFloat.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DataListFloat.java new file mode 100644 index 000000000000..edcb5fef7766 --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DataListFloat.java @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget.remotecompose.core.operations; + +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT_ARRAY; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; + +import com.android.internal.widget.remotecompose.core.Operation; +import com.android.internal.widget.remotecompose.core.Operations; +import com.android.internal.widget.remotecompose.core.RemoteContext; +import com.android.internal.widget.remotecompose.core.VariableSupport; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; +import com.android.internal.widget.remotecompose.core.operations.utilities.ArrayAccess; + +import java.util.Arrays; +import java.util.List; + +public class DataListFloat implements VariableSupport, ArrayAccess, Operation { + private static final int OP_CODE = Operations.FLOAT_LIST; + private static final String CLASS_NAME = "IdListData"; + int mId; + float[] mValues; + private static final int MAX_FLOAT_ARRAY = 2000; + + public DataListFloat(int id, float[] values) { + mId = id; + mValues = values; + } + + @Override + public void updateVariables(RemoteContext context) { + // TODO add support for variables in arrays + } + + @Override + public void registerListening(RemoteContext context) { + context.addCollection(mId, this); + for (float value : mValues) { + if (Utils.isVariable(value)) { + context.listensTo(Utils.idFromNan(value), this); + } + } + } + + @Override + public void write(WireBuffer buffer) { + apply(buffer, mId, mValues); + } + + @Override + public String toString() { + return "DataListFloat[A_" + (mId & 0xFFFF) + "] " + Arrays.toString(mValues); + } + + public static void apply(WireBuffer buffer, int id, float[] values) { + buffer.start(OP_CODE); + buffer.writeInt(id); + buffer.writeInt(values.length); + for (int i = 0; i < values.length; i++) { + buffer.writeFloat(values[i]); + } + } + + public static void read(WireBuffer buffer, List<Operation> operations) { + int id = buffer.readInt(); + int len = buffer.readInt(); + if (len > MAX_FLOAT_ARRAY) { + throw new RuntimeException(len + " map entries more than max = " + MAX_FLOAT_ARRAY); + } + float[] values = new float[len]; + for (int i = 0; i < values.length; i++) { + values[i] = buffer.readFloat(); + } + DataListFloat data = new DataListFloat(id, values); + operations.add(data); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Data Operations", + OP_CODE, + CLASS_NAME) + .description("a list of Floats") + .field(INT, "id", "id the array (2xxxxx)") + .field(INT, "length", "number of floats") + .field(FLOAT_ARRAY, "values", "length", + "array of floats"); + } + + @Override + public String deepToString(String indent) { + return indent + toString(); + } + + @Override + public void apply(RemoteContext context) { + context.addCollection(mId, this); + } + + @Override + public float getFloatValue(int index) { + return mValues[index]; + } + + @Override + public float[] getFloats() { + return mValues; + } + + @Override + public int getFloatsLength() { + return mValues.length; + } +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DataListIds.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DataListIds.java new file mode 100644 index 000000000000..bde376e59d9c --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DataListIds.java @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget.remotecompose.core.operations; + +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT_ARRAY; + +import com.android.internal.widget.remotecompose.core.Operation; +import com.android.internal.widget.remotecompose.core.Operations; +import com.android.internal.widget.remotecompose.core.RemoteContext; +import com.android.internal.widget.remotecompose.core.VariableSupport; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; +import com.android.internal.widget.remotecompose.core.operations.utilities.ArrayAccess; + +import java.util.Arrays; +import java.util.List; + +public class DataListIds implements VariableSupport, ArrayAccess, Operation { + private static final int OP_CODE = Operations.ID_LIST; + private static final String CLASS_NAME = "IdListData"; + int mId; + int[] mIds; + float[] mValues; + private static final int MAX_LIST = 2000; + + public DataListIds(int id, int[] ids) { + mId = id; + mIds = ids; + mValues = new float[ids.length]; + } + + @Override + public void updateVariables(RemoteContext context) { + for (int i = 0; i < mIds.length; i++) { + int id = mIds[i]; + mValues[i] = context.getFloat(id); + } + } + + @Override + public void registerListening(RemoteContext context) { + for (int mId : mIds) { + context.listensTo(mId, this); + } + } + + @Override + public void write(WireBuffer buffer) { + apply(buffer, mId, mIds); + } + + @Override + public String toString() { + return "map " + "\"" + Arrays.toString(mIds) + "\""; + } + + public static void apply(WireBuffer buffer, int id, int[] ids) { + buffer.start(OP_CODE); + buffer.writeInt(id); + buffer.writeInt(ids.length); + for (int i = 0; i < ids.length; i++) { + buffer.writeInt(ids[i]); + } + } + + public static void read(WireBuffer buffer, List<Operation> operations) { + int id = buffer.readInt(); + int len = buffer.readInt(); + if (len > MAX_LIST) { + throw new RuntimeException(len + " list entries more than max = " + MAX_LIST); + } + int[] ids = new int[len]; + for (int i = 0; i < ids.length; i++) { + ids[i] = buffer.readInt(); + } + DataListIds data = new DataListIds(id, ids); + operations.add(data); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Data Operations", + OP_CODE, + CLASS_NAME) + .description("a list of id's") + .field(INT, "id", "id the array") + .field(INT, "length", "number of ids") + .field(INT_ARRAY, "ids[n]", "length", + "ids of other variables"); + + } + + @Override + public String deepToString(String indent) { + return indent + toString(); + } + + @Override + public void apply(RemoteContext context) { + context.addCollection(mId, this); + } + + @Override + public float getFloatValue(int index) { + return mValues[index]; + } + + @Override + public float[] getFloats() { + return mValues; + } + + @Override + public int getFloatsLength() { + return mValues.length; + } +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DataMapIds.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DataMapIds.java new file mode 100644 index 000000000000..53143dcf8211 --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DataMapIds.java @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget.remotecompose.core.operations; + +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.UTF8; + +import com.android.internal.widget.remotecompose.core.Operation; +import com.android.internal.widget.remotecompose.core.Operations; +import com.android.internal.widget.remotecompose.core.RemoteContext; +import com.android.internal.widget.remotecompose.core.VariableSupport; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; +import com.android.internal.widget.remotecompose.core.operations.utilities.ArrayAccess; + +import java.util.List; + +public class DataMapIds implements VariableSupport, ArrayAccess, Operation { + private static final int OP_CODE = Operations.ID_MAP; + private static final String CLASS_NAME = "IdMapData"; + int mId; + String[] mNames; + int[] mIds; + float[] mValues; + private static final int MAX_MAP = 2000; + + public DataMapIds(int id, String[] names, int[] ids) { + mId = id; + mNames = names; + mIds = ids; + mValues = new float[ids.length]; + + } + + @Override + public void updateVariables(RemoteContext context) { + for (int i = 0; i < mIds.length; i++) { + int id = mIds[i]; + mValues[i] = context.getFloat(id); + } + } + + @Override + public void registerListening(RemoteContext context) { + for (int mId : mIds) { + context.listensTo(mId, this); + } + } + + @Override + public void write(WireBuffer buffer) { + apply(buffer, mId, mNames, mIds); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder("DataMapIds "); + for (int i = 0; i < mNames.length; i++) { + if (i != 0) { + builder.append(" "); + } + builder.append(mNames[i]); + builder.append("["); + builder.append(mIds[i]); + builder.append("]"); + + } + return builder.toString(); + } + + public static void apply(WireBuffer buffer, int id, String[] names, int[] ids) { + buffer.start(OP_CODE); + buffer.writeInt(id); + buffer.writeInt(names.length); + for (int i = 0; i < names.length; i++) { + buffer.writeUTF8(names[i]); + buffer.writeInt(ids[i]); + } + } + + public static void read(WireBuffer buffer, List<Operation> operations) { + int id = buffer.readInt(); + int len = buffer.readInt(); + if (len > MAX_MAP) { + throw new RuntimeException(len + " map entries more than max = " + MAX_MAP); + } + String[] names = new String[len]; + int[] ids = new int[len]; + for (int i = 0; i < names.length; i++) { + names[i] = buffer.readUTF8(); + ids[i] = buffer.readInt(); + } + DataMapIds data = new DataMapIds(id, names, ids); + operations.add(data); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Data Operations", + OP_CODE, + CLASS_NAME) + .description("Encode a collection of name id pairs") + .field(INT, "id", "id the array") + .field(INT, "length", "number of entries") + .field(INT, "names[0]", "length", + "path encoded as floats") + .field(UTF8, "id[0]", "length", + "path encoded as floats"); + } + + @Override + public String deepToString(String indent) { + return indent + toString(); + } + + @Override + public void apply(RemoteContext context) { + context.addCollection(mId, this); + } + + @Override + public float getFloatValue(int index) { + return mValues[index]; + } + + @Override + public float[] getFloats() { + return mValues; + } + + @Override + public int getFloatsLength() { + return mValues.length; + } +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawArc.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawArc.java index c1768647bde6..d37722917b27 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawArc.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawArc.java @@ -15,23 +15,85 @@ */ package com.android.internal.widget.remotecompose.core.operations; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; + +import java.util.List; public class DrawArc extends DrawBase6 { - public static final Companion COMPANION = - new Companion(Operations.DRAW_ARC) { - @Override - public Operation construct(float v1, - float v2, - float v3, - float v4, - float v5, - float v6) { - return new DrawArc(v1, v2, v3, v4, v5, v6); - } - }; + public static final int OP_CODE = Operations.DRAW_ARC; + private static final String CLASS_NAME = "DrawArc"; + + public static void read(WireBuffer buffer, List<Operation> operations) { + Maker m = DrawArc::new; + read(m, buffer, operations); + } + + public static int id() { + return OP_CODE; + } + + /** + * Writes out the operation to the buffer + * @param buffer the buffer to write to + * @param v1 The left side of the Oval + * @param v2 The top of the Oval + * @param v3 The right side of the Oval + * @param v4 The bottom of the Oval + * @param v5 Starting angle (in degrees) where the arc begins + * @param v6 Sweep angle (in degrees) measured clockwise + */ + public static void apply(WireBuffer buffer, + float v1, + float v2, + float v3, + float v4, + float v5, + float v6) { + buffer.start(OP_CODE); + buffer.writeFloat(v1); + buffer.writeFloat(v2); + buffer.writeFloat(v3); + buffer.writeFloat(v4); + buffer.writeFloat(v5); + buffer.writeFloat(v6); + } + + protected void write(WireBuffer buffer, + float v1, + float v2, + float v3, + float v4, + float v5, + float v6) { + apply(buffer, v1, v2, v3, v4, v5, v6); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Canvas Operations", + OP_CODE, + CLASS_NAME) + .description("Draw the specified arc" + + "which will be scaled to fit inside the specified oval") + .field(FLOAT, "left", + "The left side of the Oval") + .field(FLOAT, "top", + "The top of the Oval") + .field(FLOAT, "right", + "The right side of the Oval") + .field(FLOAT, "bottom", + "The bottom of the Oval") + .field(FLOAT, "startAngle", + "Starting angle (in degrees) where the arc begins") + .field(FLOAT, "sweepAngle", + "Sweep angle (in degrees) measured clockwise"); + } + public DrawArc(float v1, float v2, @@ -43,7 +105,6 @@ public class DrawArc extends DrawBase6 { mName = "DrawArc"; } - @Override public void paint(PaintContext context) { context.drawArc(mV1, mV2, mV3, mV4, mV5, mV6); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase2.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase2.java index 0963c1337b70..97eb76bfaaa9 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase2.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase2.java @@ -17,9 +17,7 @@ package com.android.internal.widget.remotecompose.core.operations; import static com.android.internal.widget.remotecompose.core.operations.Utils.floatToString; -import com.android.internal.widget.remotecompose.core.CompanionOperation; import com.android.internal.widget.remotecompose.core.Operation; -import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintOperation; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.VariableSupport; @@ -32,14 +30,6 @@ import java.util.List; */ public abstract class DrawBase2 extends PaintOperation implements VariableSupport { - public static final Companion COMPANION = - new Companion(Operations.DRAW_CIRCLE) { - @Override - public Operation construct(float x1, float y1) { - // subclass should return new DrawX(x1, y1); - return null; - } - }; protected String mName = "DrawRectBase"; float mV1; float mV2; @@ -71,9 +61,17 @@ public abstract class DrawBase2 extends PaintOperation } } + @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mV1, mV2); + write(buffer, mV1, mV2); + } + + protected abstract void write(WireBuffer buffer, float v1, float v2); + + protected interface Maker { + DrawBase2 create(float v1, + float v2); } @Override @@ -81,54 +79,42 @@ public abstract class DrawBase2 extends PaintOperation return mName + " " + floatToString(mV1) + " " + floatToString(mV2); } - public static class Companion implements CompanionOperation { - public final int OP_CODE; - protected Companion(int code) { - OP_CODE = code; - } - - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - float v1 = buffer.readFloat(); - float v2 = buffer.readFloat(); + public static void read(Maker maker, WireBuffer buffer, List<Operation> operations) { + float v1 = buffer.readFloat(); + float v2 = buffer.readFloat(); - Operation op = construct(v1, v2); - operations.add(op); - } + Operation op = maker.create(v1, v2); + operations.add(op); + } - /** - * Override to construct a 2 float value operation - * @param x1 - * @param y1 - * @return - */ - public Operation construct(float x1, float y1) { - return null; - } + /** + * Override to construct a 2 float value operation + * + * @param x1 + * @param y1 + * @return + */ + public Operation construct(float x1, float y1) { + return null; + } - @Override - public String name() { - return "DrawRect"; - } - @Override - public int id() { - return OP_CODE; - } + /** + * Writes out the operation to the buffer + * + * @param buffer + * @param opCode + * @param x1 + * @param y1 + */ + protected static void write(WireBuffer buffer, + int opCode, + float x1, + float y1) { + buffer.start(opCode); + buffer.writeFloat(x1); + buffer.writeFloat(y1); - /** - * Writes out the operation to the buffer - * @param buffer - * @param x1 - * @param y1 - */ - public void apply(WireBuffer buffer, - float x1, - float y1) { - buffer.start(OP_CODE); - buffer.writeFloat(x1); - buffer.writeFloat(y1); - } } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase3.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase3.java index 5a4a9f3754df..2d1d3eb4b78c 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase3.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase3.java @@ -17,9 +17,7 @@ package com.android.internal.widget.remotecompose.core.operations; import static com.android.internal.widget.remotecompose.core.operations.Utils.floatToString; -import com.android.internal.widget.remotecompose.core.CompanionOperation; import com.android.internal.widget.remotecompose.core.Operation; -import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintOperation; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.VariableSupport; @@ -32,14 +30,7 @@ import java.util.List; */ public abstract class DrawBase3 extends PaintOperation implements VariableSupport { - public static final Companion COMPANION = - new Companion(Operations.DRAW_CIRCLE) { - @Override - public Operation construct(float x1, float y1, float x2) { - // subclass should return new DrawX(x1, y1, x2, y2); - return null; - } - }; + protected String mName = "DrawRectBase"; float mV1; float mV2; @@ -86,7 +77,18 @@ public abstract class DrawBase3 extends PaintOperation @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mV1, mV2, mV3); + write(buffer, mV1, mV2, mV3); + } + + protected abstract void write(WireBuffer buffer, + float v1, + float v2, + float v3); + + interface Maker { + DrawBase3 create(float v1, + float v2, + float v3); } @Override @@ -95,63 +97,26 @@ public abstract class DrawBase3 extends PaintOperation + " " + floatToString(mV3); } - public static class Companion implements CompanionOperation { - public final int OP_CODE; - - protected Companion(int code) { - OP_CODE = code; - } - - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - float v1 = buffer.readFloat(); - float v2 = buffer.readFloat(); - float v3 = buffer.readFloat(); - - Operation op = construct(v1, v2, v3); - operations.add(op); - } - - /** - * Construct and Operation from the 3 variables. - * This must be overridden by subclasses - * @param x1 - * @param y1 - * @param x2 - * @return - */ - public Operation construct(float x1, - float y1, - float x2) { - return null; - } - - @Override - public String name() { - return "DrawRect"; - } - - @Override - public int id() { - return OP_CODE; - } - - /** - * Writes out the operation to the buffer - * @param buffer - * @param x1 - * @param y1 - * @param x2 - */ - public void apply(WireBuffer buffer, - float x1, - float y1, - float x2) { - buffer.start(OP_CODE); - buffer.writeFloat(x1); - buffer.writeFloat(y1); - buffer.writeFloat(x2); + public static void read(Maker maker, WireBuffer buffer, List<Operation> operations) { + float v1 = buffer.readFloat(); + float v2 = buffer.readFloat(); + float v3 = buffer.readFloat(); + Operation op = maker.create(v1, v2, v3); + operations.add(op); + } - } + /** + * Construct and Operation from the 3 variables. + * This must be overridden by subclasses + * + * @param x1 + * @param y1 + * @param x2 + * @return + */ + public Operation construct(float x1, + float y1, + float x2) { + return null; } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase4.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase4.java index 53a3aa917d0f..943c5a44b5ac 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase4.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase4.java @@ -17,9 +17,7 @@ package com.android.internal.widget.remotecompose.core.operations; import static com.android.internal.widget.remotecompose.core.operations.Utils.floatToString; -import com.android.internal.widget.remotecompose.core.CompanionOperation; import com.android.internal.widget.remotecompose.core.Operation; -import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintOperation; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.VariableSupport; @@ -32,14 +30,6 @@ import java.util.List; */ public abstract class DrawBase4 extends PaintOperation implements VariableSupport { - public static final Companion COMPANION = - new Companion(Operations.DRAW_RECT) { - @Override - public Operation construct(float x1, float y1, float x2, float y2) { - // return new DrawRectBase(x1, y1, x2, y2); - return null; - } - }; protected String mName = "DrawRectBase"; protected float mX1; protected float mY1; @@ -96,7 +86,20 @@ public abstract class DrawBase4 extends PaintOperation @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mX1, mY1, mX2, mY2); + write(buffer, mX1, mY1, mX2, mY2); + } + + protected abstract void write(WireBuffer buffer, + float v1, + float v2, + float v3, + float v4); + + protected interface Maker { + DrawBase4 create(float v1, + float v2, + float v3, + float v4); } @Override @@ -105,67 +108,54 @@ public abstract class DrawBase4 extends PaintOperation + " " + floatToString(mX2Value, mX2) + " " + floatToString(mY2Value, mY2); } - public static class Companion implements CompanionOperation { - public final int OP_CODE; - - protected Companion(int code) { - OP_CODE = code; - } - - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - float sLeft = buffer.readFloat(); - float srcTop = buffer.readFloat(); - float srcRight = buffer.readFloat(); - float srcBottom = buffer.readFloat(); - - Operation op = construct(sLeft, srcTop, srcRight, srcBottom); - operations.add(op); - } + public static void read(Maker maker, WireBuffer buffer, List<Operation> operations) { + float v1 = buffer.readFloat(); + float v2 = buffer.readFloat(); + float v3 = buffer.readFloat(); + float v4 = buffer.readFloat(); - /** - * Construct and Operation from the 3 variables. - * @param x1 - * @param y1 - * @param x2 - * @param y2 - * @return - */ - public Operation construct(float x1, - float y1, - float x2, - float y2) { - return null; - } + Operation op = maker.create(v1, v2, v3, v4); + operations.add(op); + } - @Override - public String name() { - return "DrawRect"; - } + /** + * Construct and Operation from the 3 variables. + * + * @param x1 + * @param y1 + * @param x2 + * @param y2 + * @return + */ + public Operation construct(float x1, + float y1, + float x2, + float y2) { + return null; + } - @Override - public int id() { - return OP_CODE; - } - /** - * Writes out the operation to the buffer - * @param buffer - * @param x1 - * @param y1 - * @param x2 - * @param y2 - */ - public void apply(WireBuffer buffer, - float x1, - float y1, - float x2, - float y2) { - buffer.start(OP_CODE); - buffer.writeFloat(x1); - buffer.writeFloat(y1); - buffer.writeFloat(x2); - buffer.writeFloat(y2); - } + /** + * Writes out the operation to the buffer + * + * @param buffer + * @param opCode + * @param x1 + * @param y1 + * @param x2 + * @param y2 + */ + protected static void write(WireBuffer buffer, + int opCode, + float x1, + float y1, + float x2, + float y2) { + buffer.start(opCode); + buffer.writeFloat(x1); + buffer.writeFloat(y1); + buffer.writeFloat(x2); + buffer.writeFloat(y2); } } + diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase6.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase6.java index 2f4335e7f412..767a36d03ace 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase6.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase6.java @@ -17,9 +17,7 @@ package com.android.internal.widget.remotecompose.core.operations; import static com.android.internal.widget.remotecompose.core.operations.Utils.floatToString; -import com.android.internal.widget.remotecompose.core.CompanionOperation; import com.android.internal.widget.remotecompose.core.Operation; -import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintOperation; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.VariableSupport; @@ -32,13 +30,6 @@ import java.util.List; */ public abstract class DrawBase6 extends PaintOperation implements VariableSupport { - public static final Companion COMPANION = - new Companion(Operations.DRAW_RECT) { - public Operation construct(float x1, float y1, float x2, float y2) { - // return new DrawRectBase(x1, y1, x2, y2); - return null; - } - }; protected String mName = "DrawRectBase"; float mV1; float mV2; @@ -115,88 +106,67 @@ public abstract class DrawBase6 extends PaintOperation @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mV1, mV2, mV3, mV4, mV5, mV6); + write(buffer, mV1, mV2, mV3, mV4, mV5, mV6); } + protected abstract void write(WireBuffer buffer, + float v1, + float v2, + float v3, + float v4, + float v5, + float v6); + @Override public String toString() { return mName + " " + floatToString(mV1) + " " + floatToString(mV2) + " " + floatToString(mV3) + " " + floatToString(mV4); } - public static class Companion implements CompanionOperation { - public final int OP_CODE; - - protected Companion(int code) { - OP_CODE = code; - } + interface Maker { + DrawBase6 create(float v1, + float v2, + float v3, + float v4, + float v5, + float v6); + } - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - float sv1 = buffer.readFloat(); - float sv2 = buffer.readFloat(); - float sv3 = buffer.readFloat(); - float sv4 = buffer.readFloat(); - float sv5 = buffer.readFloat(); - float sv6 = buffer.readFloat(); - - Operation op = construct(sv1, sv2, sv3, sv4, sv5, sv6); - operations.add(op); - } + public static void read(Maker build, WireBuffer buffer, List<Operation> operations) { + float sv1 = buffer.readFloat(); + float sv2 = buffer.readFloat(); + float sv3 = buffer.readFloat(); + float sv4 = buffer.readFloat(); + float sv5 = buffer.readFloat(); + float sv6 = buffer.readFloat(); - /** - * writes out a the operation to the buffer. - * @param v1 - * @param v2 - * @param v3 - * @param v4 - * @param v5 - * @param v6 - * @return - */ - public Operation construct(float v1, - float v2, - float v3, - float v4, - float v5, - float v6) { - return null; - } + Operation op = build.create(sv1, sv2, sv3, sv4, sv5, sv6); + operations.add(op); + } - @Override - public String name() { - return "DrawRect"; - } + /** + * writes out a the operation to the buffer. + * + * @param v1 + * @param v2 + * @param v3 + * @param v4 + * @param v5 + * @param v6 + * @return + */ + public Operation construct(float v1, + float v2, + float v3, + float v4, + float v5, + float v6) { + return null; + } - @Override - public int id() { - return OP_CODE; - } - /** - * Writes out the operation to the buffer - * @param buffer - * @param v1 - * @param v2 - * @param v3 - * @param v4 - * @param v5 - * @param v6 - */ - public void apply(WireBuffer buffer, - float v1, - float v2, - float v3, - float v4, - float v5, - float v6) { - buffer.start(OP_CODE); - buffer.writeFloat(v1); - buffer.writeFloat(v2); - buffer.writeFloat(v3); - buffer.writeFloat(v4); - buffer.writeFloat(v5); - buffer.writeFloat(v6); - } + public static String name() { + return "DrawBase6"; } + } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmap.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmap.java index ca40d12fd3f9..2748f4c3c369 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmap.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmap.java @@ -15,7 +15,9 @@ */ package com.android.internal.widget.remotecompose.core.operations; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; @@ -23,11 +25,13 @@ import com.android.internal.widget.remotecompose.core.PaintOperation; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.VariableSupport; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import java.util.List; public class DrawBitmap extends PaintOperation implements VariableSupport { - public static final Companion COMPANION = new Companion(); + private static final int OP_CODE = Operations.DRAW_BITMAP; + private static final String CLASS_NAME = "DrawBitmap"; float mLeft; float mTop; float mRight; @@ -84,7 +88,7 @@ public class DrawBitmap extends PaintOperation implements VariableSupport { @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mId, mLeft, mTop, mRight, mBottom, mDescriptionId); + apply(buffer, mId, mLeft, mTop, mRight, mBottom, mDescriptionId); } @Override @@ -93,51 +97,59 @@ public class DrawBitmap extends PaintOperation implements VariableSupport { + " " + mRight + " " + mBottom + ";"; } - public static class Companion implements CompanionOperation { - private Companion() { - } + public static void read(WireBuffer buffer, List<Operation> operations) { + int id = buffer.readInt(); + float sLeft = buffer.readFloat(); + float srcTop = buffer.readFloat(); + float srcRight = buffer.readFloat(); + float srcBottom = buffer.readFloat(); + int discriptionId = buffer.readInt(); - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int id = buffer.readInt(); - float sLeft = buffer.readFloat(); - float srcTop = buffer.readFloat(); - float srcRight = buffer.readFloat(); - float srcBottom = buffer.readFloat(); - int discriptionId = buffer.readInt(); - - DrawBitmap op = new DrawBitmap(id, sLeft, srcTop, srcRight, srcBottom, discriptionId); - operations.add(op); - } + DrawBitmap op = new DrawBitmap(id, sLeft, srcTop, srcRight, srcBottom, discriptionId); + operations.add(op); + } - @Override - public String name() { - return "DrawOval"; - } + public static String name() { + return CLASS_NAME; + } - @Override - public int id() { - return Operations.DRAW_BITMAP; - } + public static int id() { + return OP_CODE; + } - public void apply(WireBuffer buffer, - int id, - float left, - float top, - float right, - float bottom, - int descriptionId) { - buffer.start(Operations.DRAW_BITMAP); - buffer.writeInt(id); - buffer.writeFloat(left); - buffer.writeFloat(top); - buffer.writeFloat(right); - buffer.writeFloat(bottom); - buffer.writeInt(descriptionId); - } + public static void apply(WireBuffer buffer, + int id, + float left, + float top, + float right, + float bottom, + int descriptionId) { + buffer.start(Operations.DRAW_BITMAP); + buffer.writeInt(id); + buffer.writeFloat(left); + buffer.writeFloat(top); + buffer.writeFloat(right); + buffer.writeFloat(bottom); + buffer.writeInt(descriptionId); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Draw Operations", + OP_CODE, + CLASS_NAME) + .description("Draw a bitmap") + .field(INT, "id", "id of float") + .field(FLOAT, "left", + "The left side of the image") + .field(FLOAT, "top", + "The top of the image") + .field(FLOAT, "right", + "The right side of the image") + .field(FLOAT, "bottom", + "The bottom of the image") + .field(INT, "descriptionId", "id of string"); } - @Override public void paint(PaintContext context) { context.drawBitmap(mId, mOutputLeft, mOutputTop, diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapInt.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapInt.java index c2a56e7256d6..561d52720a67 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapInt.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapInt.java @@ -15,12 +15,14 @@ */ package com.android.internal.widget.remotecompose.core.operations; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; import com.android.internal.widget.remotecompose.core.PaintOperation; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import java.util.List; @@ -28,6 +30,8 @@ import java.util.List; * Operation to draw a given cached bitmap */ public class DrawBitmapInt extends PaintOperation { + private static final int OP_CODE = Operations.DRAW_BITMAP_INT; + private static final String CLASS_NAME = "DrawBitmapInt"; int mImageId; int mSrcLeft; int mSrcTop; @@ -38,7 +42,6 @@ public class DrawBitmapInt extends PaintOperation { int mDstRight; int mDstBottom; int mContentDescId = 0; - public static final Companion COMPANION = new Companion(); public DrawBitmapInt(int imageId, int srcLeft, @@ -64,7 +67,7 @@ public class DrawBitmapInt extends PaintOperation { @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mImageId, mSrcLeft, mSrcTop, mSrcRight, mSrcBottom, + apply(buffer, mImageId, mSrcLeft, mSrcTop, mSrcRight, mSrcBottom, mDstLeft, mDstTop, mDstRight, mDstBottom, mContentDescId); } @@ -75,54 +78,73 @@ public class DrawBitmapInt extends PaintOperation { + "- " + mDstLeft + " " + mDstTop + " " + mDstRight + " " + mDstBottom + ";"; } - public static class Companion implements CompanionOperation { - private Companion() { - } - - @Override - public String name() { - return "DrawBitmapInt"; - } - - @Override - public int id() { - return Operations.DRAW_BITMAP; - } - - public void apply(WireBuffer buffer, int imageId, - int srcLeft, int srcTop, int srcRight, int srcBottom, - int dstLeft, int dstTop, int dstRight, int dstBottom, - int cdId) { - buffer.start(Operations.DRAW_BITMAP_INT); - buffer.writeInt(imageId); - buffer.writeInt(srcLeft); - buffer.writeInt(srcTop); - buffer.writeInt(srcRight); - buffer.writeInt(srcBottom); - buffer.writeInt(dstLeft); - buffer.writeInt(dstTop); - buffer.writeInt(dstRight); - buffer.writeInt(dstBottom); - buffer.writeInt(cdId); - } - - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int imageId = buffer.readInt(); - int sLeft = buffer.readInt(); - int srcTop = buffer.readInt(); - int srcRight = buffer.readInt(); - int srcBottom = buffer.readInt(); - int dstLeft = buffer.readInt(); - int dstTop = buffer.readInt(); - int dstRight = buffer.readInt(); - int dstBottom = buffer.readInt(); - int cdId = buffer.readInt(); - DrawBitmapInt op = new DrawBitmapInt(imageId, sLeft, srcTop, srcRight, srcBottom, - dstLeft, dstTop, dstRight, dstBottom, cdId); - - operations.add(op); - } + + public static String name() { + return CLASS_NAME; + } + + public static int id() { + return OP_CODE; + } + + public static void apply(WireBuffer buffer, int imageId, + int srcLeft, int srcTop, int srcRight, int srcBottom, + int dstLeft, int dstTop, int dstRight, int dstBottom, + int cdId) { + buffer.start(Operations.DRAW_BITMAP_INT); + buffer.writeInt(imageId); + buffer.writeInt(srcLeft); + buffer.writeInt(srcTop); + buffer.writeInt(srcRight); + buffer.writeInt(srcBottom); + buffer.writeInt(dstLeft); + buffer.writeInt(dstTop); + buffer.writeInt(dstRight); + buffer.writeInt(dstBottom); + buffer.writeInt(cdId); + } + + public static void read(WireBuffer buffer, List<Operation> operations) { + int imageId = buffer.readInt(); + int sLeft = buffer.readInt(); + int srcTop = buffer.readInt(); + int srcRight = buffer.readInt(); + int srcBottom = buffer.readInt(); + int dstLeft = buffer.readInt(); + int dstTop = buffer.readInt(); + int dstRight = buffer.readInt(); + int dstBottom = buffer.readInt(); + int cdId = buffer.readInt(); + DrawBitmapInt op = new DrawBitmapInt(imageId, sLeft, srcTop, srcRight, srcBottom, + dstLeft, dstTop, dstRight, dstBottom, cdId); + + operations.add(op); + } + + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Draw Operations", + OP_CODE, + CLASS_NAME) + .description("Draw a bitmap using integer coordinates") + .field(INT, "id", "id of bitmap") + .field(INT, "srcLeft", + "The left side of the image") + .field(INT, "srcTop", + "The top of the image") + .field(INT, "srcRight", + "The right side of the image") + .field(INT, "srcBottom", + "The bottom of the image") + .field(INT, "dstLeft", + "The left side of the image") + .field(INT, "dstTop", + "The top of the image") + .field(INT, "dstRight", + "The right side of the image") + .field(INT, "dstBottom", + "The bottom of the image") + .field(INT, "cdId", "id of string"); } @Override diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawCircle.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawCircle.java index 3a22e4f72720..e39a19171cf0 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawCircle.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawCircle.java @@ -1,31 +1,80 @@ package com.android.internal.widget.remotecompose.core.operations; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; + +import java.util.List; public class DrawCircle extends DrawBase3 { - public static final Companion COMPANION = - new Companion(Operations.DRAW_CIRCLE) { - @Override - public Operation construct(float x1, - float y1, - float x2 - ) { - return new DrawCircle(x1, y1, x2); - } - }; + private static final int OP_CODE = Operations.DRAW_CIRCLE; + private static final String CLASS_NAME = "DrawCircle"; + + public static void read(WireBuffer buffer, List<Operation> operations) { + Maker m = DrawCircle::new; + read(m, buffer, operations); + } + + public static int id() { + return OP_CODE; + } + + public static String name() { + return CLASS_NAME; + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Canvas Operations", + OP_CODE, + CLASS_NAME) + .description("Draw a Circle") + .field(FLOAT, "centerX", + "The x-coordinate of the center of the circle to be drawn") + .field(FLOAT, "centerY", + "The y-coordinate of the center of the circle to be drawn") + .field(FLOAT, "radius", + "The radius of the circle to be drawn"); + } + + protected void write(WireBuffer buffer, + float v1, + float v2, + float v3) { + apply(buffer, v1, v2, v3); + } public DrawCircle( float left, float top, float right) { super(left, top, right); - mName = "DrawCircle"; + mName = CLASS_NAME; } @Override public void paint(PaintContext context) { context.drawCircle(mV1, mV2, mV3); } + + /** + * Writes out the operation to the buffer + * + * @param buffer + * @param x1 + * @param y1 + * @param x2 + */ + public static void apply(WireBuffer buffer, + float x1, + float y1, + float x2) { + buffer.start(OP_CODE); + buffer.writeFloat(x1); + buffer.writeFloat(y1); + buffer.writeFloat(x2); + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawLine.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawLine.java index c70c6eaa449d..a7276b56049f 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawLine.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawLine.java @@ -15,20 +15,58 @@ */ package com.android.internal.widget.remotecompose.core.operations; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; +import com.android.internal.widget.remotecompose.core.SerializableToString; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; +import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer; + +import java.util.List; + +public class DrawLine extends DrawBase4 implements SerializableToString { + private static final int OP_CODE = Operations.DRAW_LINE; + private static final String CLASS_NAME = "DrawLine"; + + public static void read(WireBuffer buffer, List<Operation> operations) { + Maker m = DrawLine::new; + read(m, buffer, operations); + } -public class DrawLine extends DrawBase4 { - public static final Companion COMPANION = new Companion(Operations.DRAW_LINE) { - @Override - public Operation construct(float x1, - float y1, - float x2, - float y2) { - return new DrawLine(x1, y1, x2, y2); - } - }; + + public static int id() { + return OP_CODE; + } + + public static String name() { + return CLASS_NAME; + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Canvas Operations", + OP_CODE, + CLASS_NAME) + .description("Draw a line segment") + .field(FLOAT, "startX", + "The x-coordinate of the start point of the line") + .field(FLOAT, "startY", + "The y-coordinate of the start point of the line") + .field(FLOAT, "endX", + "The x-coordinate of the end point of the line") + .field(FLOAT, "endY", + "The y-coordinate of the end point of the line"); + } + + protected void write(WireBuffer buffer, + float v1, + float v2, + float v3, + float v4) { + apply(buffer, v1, v2, v3, v4); + } public DrawLine( float left, @@ -41,10 +79,45 @@ public class DrawLine extends DrawBase4 { @Override public void paint(PaintContext context) { - context.drawLine(mX1, - mY1, - mX2, - mY2); + context.drawLine(mX1, mY1, mX2, mY2); + } + + /** + * Writes out the DrawLine to the buffer + * + * @param buffer buffer to write to + * @param x1 start x of line + * @param y1 start y of the line + * @param x2 end x of the line + * @param y2 end y of the line + */ + public static void apply(WireBuffer buffer, + float x1, + float y1, + float x2, + float y2) { + write(buffer, OP_CODE, x1, y1, x2, y2); } + public void serializeToString(int indent, StringSerializer serializer) { + String x1 = "" + mX1; + if (Float.isNaN(mX1Value)) { + x1 = "[" + Utils.idFromNan(mX1Value) + " = " + mX1 + "]"; + } + String y1 = "" + mY1; + if (Float.isNaN(mY1Value)) { + y1 = "[" + Utils.idFromNan(mY1Value) + " = " + mY1 + "]"; + } + String x2 = "" + mX2; + if (Float.isNaN(mX2Value)) { + x2 = "[" + Utils.idFromNan(mX2Value) + " = " + mX2 + "]"; + } + String y2 = "" + mY2; + if (Float.isNaN(mY2Value)) { + y2 = "[" + Utils.idFromNan(mY2Value) + " = " + mY2 + "]"; + } + serializer.append(indent, CLASS_NAME + + "(" + x1 + ", " + y1 + ", " + x2 + ", " + y2 + ")" + ); + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawOval.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawOval.java index ba1799422e80..01761efbb9ed 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawOval.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawOval.java @@ -15,21 +15,60 @@ */ package com.android.internal.widget.remotecompose.core.operations; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; + +import java.util.List; public class DrawOval extends DrawBase4 { - public static final Companion COMPANION = - new Companion(Operations.DRAW_OVAL) { - @Override - public Operation construct(float x1, - float y1, - float x2, - float y2) { - return new DrawOval(x1, y1, x2, y2); - } - }; + private static final int OP_CODE = Operations.DRAW_OVAL; + private static final String CLASS_NAME = "DrawOval"; + + public static void read(WireBuffer buffer, List<Operation> operations) { + Maker m = DrawOval::new; + read(m, buffer, operations); + } + + public static int id() { + return OP_CODE; + } + + public static String name() { + return CLASS_NAME; + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Canvas Operations", + OP_CODE, + CLASS_NAME) + .description("Draw the specified oval") + .field(FLOAT, "left", + "The left side of the oval") + .field(FLOAT, "top", + "The top of the oval") + .field(FLOAT, "right", + "The right side of the oval") + .field(FLOAT, "bottom", + "The bottom of the oval"); + } + + protected void write(WireBuffer buffer, + float v1, + float v2, + float v3, + float v4) { + apply(buffer, v1, v2, v3, v4); + } + + @Override + public void write(WireBuffer buffer) { + apply(buffer, mX1, mY1, mX2, mY2); + } public DrawOval( float left, @@ -37,11 +76,27 @@ public class DrawOval extends DrawBase4 { float right, float bottom) { super(left, top, right, bottom); - mName = "DrawOval"; + mName = CLASS_NAME; } @Override public void paint(PaintContext context) { context.drawOval(mX1, mY1, mX2, mY2); } + /** + * Writes out the DrawOval to the buffer + * + * @param buffer buffer to write to + * @param x1 start x of DrawOval + * @param y1 start y of the DrawOval + * @param x2 end x of the DrawOval + * @param y2 end y of the DrawOval + */ + public static void apply(WireBuffer buffer, + float x1, + float y1, + float x2, + float y2) { + write(buffer, OP_CODE, x1, y1, x2, y2); + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawPath.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawPath.java index 6dbc5a628c98..bc2c53a9a5ba 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawPath.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawPath.java @@ -15,17 +15,21 @@ */ package com.android.internal.widget.remotecompose.core.operations; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; import com.android.internal.widget.remotecompose.core.PaintOperation; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import java.util.List; public class DrawPath extends PaintOperation { - public static final Companion COMPANION = new Companion(); + private static final int OP_CODE = Operations.DRAW_PATH; + private static final String CLASS_NAME = "DrawPath"; + int mId; float mStart = 0; float mEnd = 1; @@ -36,7 +40,7 @@ public class DrawPath extends PaintOperation { @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mId); + apply(buffer, mId); } @Override @@ -44,33 +48,36 @@ public class DrawPath extends PaintOperation { return "DrawPath " + "[" + mId + "]" + ", " + mStart + ", " + mEnd; } - public static class Companion implements CompanionOperation { - private Companion() { - } - - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int id = buffer.readInt(); - DrawPath op = new DrawPath(id); - operations.add(op); - } - - @Override - public String name() { - return "DrawPath"; - } - - @Override - public int id() { - return Operations.DRAW_PATH; - } - - public void apply(WireBuffer buffer, int id) { - buffer.start(Operations.DRAW_PATH); - buffer.writeInt(id); - } + public static void read(WireBuffer buffer, List<Operation> operations) { + int id = buffer.readInt(); + DrawPath op = new DrawPath(id); + operations.add(op); } + + public static String name() { + return CLASS_NAME; + } + + + public static int id() { + return Operations.DRAW_PATH; + } + + public static void apply(WireBuffer buffer, int id) { + buffer.start(Operations.DRAW_PATH); + buffer.writeInt(id); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Draw Operations", + OP_CODE, + CLASS_NAME) + .description("Draw a bitmap using integer coordinates") + .field(INT, "id", "id of path"); + } + + @Override public void paint(PaintContext context) { context.drawPath(mId, mStart, mEnd); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRect.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRect.java index 633aed4a4dbe..ad17fe743b76 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRect.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRect.java @@ -15,24 +15,60 @@ */ package com.android.internal.widget.remotecompose.core.operations; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; + +import java.util.List; /** * Draw a Rectangle */ public class DrawRect extends DrawBase4 { - public static final Companion COMPANION = - new Companion(Operations.DRAW_RECT) { - @Override - public Operation construct(float x1, - float y1, - float x2, - float y2) { - return new DrawRect(x1, y1, x2, y2); - } - }; + private static final int OP_CODE = Operations.DRAW_RECT; + private static final String CLASS_NAME = "DrawRect"; + + public static void read(WireBuffer buffer, List<Operation> operations) { + Maker m = DrawRect::new; + read(m, buffer, operations); + } + + + public static int id() { + return OP_CODE; + } + + public static String name() { + return CLASS_NAME; + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Canvas Operations", + OP_CODE, + CLASS_NAME) + .description("Draw the specified rectangle") + .field(FLOAT, "left", + "The left side of the rectangle") + .field(FLOAT, "top", + "The top of the rectangle") + .field(FLOAT, "right", + "The right side of the rectangle") + .field(FLOAT, "bottom", + "The bottom of the rectangle"); + } + + + protected void write(WireBuffer buffer, + float v1, + float v2, + float v3, + float v4) { + apply(buffer, v1, v2, v3, v4); + } public DrawRect( float left, @@ -40,7 +76,7 @@ public class DrawRect extends DrawBase4 { float right, float bottom) { super(left, top, right, bottom); - mName = "DrawRect"; + mName = CLASS_NAME; } @Override @@ -48,4 +84,20 @@ public class DrawRect extends DrawBase4 { context.drawRect(mX1, mY1, mX2, mY2); } + /** + * Writes out the DrawRect to the buffer + * + * @param buffer buffer to write to + * @param x1 left x of rect + * @param y1 top y of the rect + * @param x2 right x of the rect + * @param y2 bottom y of the rect + */ + public static void apply(WireBuffer buffer, + float x1, + float y1, + float x2, + float y2) { + write(buffer, OP_CODE, x1, y1, x2, y2); + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRoundRect.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRoundRect.java index b9d0a6728b95..908e03a5191c 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRoundRect.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRoundRect.java @@ -15,26 +15,89 @@ */ package com.android.internal.widget.remotecompose.core.operations; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; + +import java.util.List; /** * Draw a rounded rectangle */ public class DrawRoundRect extends DrawBase6 { - public static final Companion COMPANION = - new Companion(Operations.DRAW_ROUND_RECT) { - @Override - public Operation construct(float v1, - float v2, - float v3, - float v4, - float v5, - float v6) { - return new DrawRoundRect(v1, v2, v3, v4, v5, v6); - } - }; + private static final int OP_CODE = Operations.DRAW_ROUND_RECT; + private static final String CLASS_NAME = "DrawRoundRect"; + + + public static void read(WireBuffer buffer, List<Operation> operations) { + Maker m = DrawRoundRect::new; + read(m, buffer, operations); + } + + public static int id() { + return OP_CODE; + } + + /** + * Writes out the operation to the buffer + * + * @param buffer The buffer to write to + * @param v1 The left side of the rect + * @param v2 The top of the rect + * @param v3 The right side of the rect + * @param v4 The bottom of the rect + * @param v5 The x-radius of the oval used to round the corners + * @param v6 The y-radius of the oval used to round the corners + */ + public static void apply(WireBuffer buffer, + float v1, + float v2, + float v3, + float v4, + float v5, + float v6) { + buffer.start(OP_CODE); + buffer.writeFloat(v1); + buffer.writeFloat(v2); + buffer.writeFloat(v3); + buffer.writeFloat(v4); + buffer.writeFloat(v5); + buffer.writeFloat(v6); + } + + protected void write(WireBuffer buffer, + float v1, + float v2, + float v3, + float v4, + float v5, + float v6) { + apply(buffer, v1, v2, v3, v4, v5, v6); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Canvas Operations", + OP_CODE, + CLASS_NAME) + .description("Draw the specified round-rect") + .field(FLOAT, "left", + "The left side of the rect") + .field(FLOAT, "top", + "The top of the rect") + .field(FLOAT, "right", + "The right side of the rect") + .field(FLOAT, "bottom", + "The bottom of the rect") + .field(FLOAT, "rx", + "The x-radius of the oval used to round the corners") + .field(FLOAT, "sweepAngle", + "The y-radius of the oval used to round the corners"); + } + public DrawRoundRect(float v1, float v2, @@ -43,7 +106,7 @@ public class DrawRoundRect extends DrawBase6 { float v5, float v6) { super(v1, v2, v3, v4, v5, v6); - mName = "ClipRect"; + mName = CLASS_NAME; } @Override diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawText.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawText.java index f8f8afdf68cd..60dddc2d610e 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawText.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawText.java @@ -15,20 +15,28 @@ */ package com.android.internal.widget.remotecompose.core.operations; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.BOOLEAN; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; +import static com.android.internal.widget.remotecompose.core.operations.Utils.floatToString; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; import com.android.internal.widget.remotecompose.core.PaintOperation; +import com.android.internal.widget.remotecompose.core.RemoteContext; +import com.android.internal.widget.remotecompose.core.VariableSupport; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import java.util.List; /** * Draw Text */ -public class DrawText extends PaintOperation { - public static final Companion COMPANION = new Companion(); +public class DrawText extends PaintOperation implements VariableSupport { + private static final int OP_CODE = Operations.DRAW_TEXT_RUN; + private static final String CLASS_NAME = "DrawText"; int mTextID; int mStart = 0; int mEnd = 0; @@ -36,6 +44,8 @@ public class DrawText extends PaintOperation { int mContextEnd = 0; float mX = 0f; float mY = 0f; + float mOutX = 0f; + float mOutY = 0f; boolean mRtl = false; public DrawText(int textID, @@ -51,86 +61,124 @@ public class DrawText extends PaintOperation { mEnd = end; mContextStart = contextStart; mContextEnd = contextEnd; - mX = x; - mY = y; + mOutX = mX = x; + mOutY = mY = y; mRtl = rtl; } @Override + public void updateVariables(RemoteContext context) { + mOutX = (Float.isNaN(mX)) + ? context.getFloat(Utils.idFromNan(mX)) : mX; + mOutY = (Float.isNaN(mY)) + ? context.getFloat(Utils.idFromNan(mY)) : mY; + } + + @Override + public void registerListening(RemoteContext context) { + if (Float.isNaN(mX)) { + context.listensTo(Utils.idFromNan(mX), this); + } + if (Float.isNaN(mY)) { + context.listensTo(Utils.idFromNan(mY), this); + } + } + + @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mTextID, mStart, mEnd, mContextStart, mContextEnd, mX, mY, mRtl); + apply(buffer, mTextID, mStart, mEnd, mContextStart, mContextEnd, mX, mY, mRtl); } @Override public String toString() { - return "DrawTextRun [" + mTextID + "] " + mStart + ", " + mEnd + ", " + mX + ", " + mY; + return "DrawTextRun [" + mTextID + "] " + mStart + ", " + mEnd + ", " + + floatToString(mX, mOutX) + ", " + floatToString(mY, mOutY); } - public static class Companion implements CompanionOperation { - private Companion() { - } + public static void read(WireBuffer buffer, List<Operation> operations) { + int text = buffer.readInt(); + int start = buffer.readInt(); + int end = buffer.readInt(); + int contextStart = buffer.readInt(); + int contextEnd = buffer.readInt(); + float x = buffer.readFloat(); + float y = buffer.readFloat(); + boolean rtl = buffer.readBoolean(); + DrawText op = new DrawText(text, start, end, contextStart, contextEnd, x, y, rtl); - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int text = buffer.readInt(); - int start = buffer.readInt(); - int end = buffer.readInt(); - int contextStart = buffer.readInt(); - int contextEnd = buffer.readInt(); - float x = buffer.readFloat(); - float y = buffer.readFloat(); - boolean rtl = buffer.readBoolean(); - DrawText op = new DrawText(text, start, end, contextStart, contextEnd, x, y, rtl); - - operations.add(op); - } + operations.add(op); + } - @Override - public String name() { - return ""; - } + public static String name() { + return CLASS_NAME; + } - @Override - public int id() { - return 0; - } - /** - * Writes out the operation to the buffer - * @param buffer - * @param textID - * @param start - * @param end - * @param contextStart - * @param contextEnd - * @param x - * @param y - * @param rtl - */ - public void apply(WireBuffer buffer, - int textID, - int start, - int end, - int contextStart, - int contextEnd, - float x, - float y, - boolean rtl) { - buffer.start(Operations.DRAW_TEXT_RUN); - buffer.writeInt(textID); - buffer.writeInt(start); - buffer.writeInt(end); - buffer.writeInt(contextStart); - buffer.writeInt(contextEnd); - buffer.writeFloat(x); - buffer.writeFloat(y); - buffer.writeBoolean(rtl); - } + public static int id() { + return OP_CODE; } + /** + * Writes out the operation to the buffer + * + * @param buffer write the command to the buffer + * @param textID id of the text + * @param start Start position + * @param end end position + * @param contextStart start of the context + * @param contextEnd end of the context + * @param x position of where to draw + * @param y position of where to draw + * @param rtl is it Right to Left text + */ + public static void apply(WireBuffer buffer, + int textID, + int start, + int end, + int contextStart, + int contextEnd, + float x, + float y, + boolean rtl) { + buffer.start(Operations.DRAW_TEXT_RUN); + buffer.writeInt(textID); + buffer.writeInt(start); + buffer.writeInt(end); + buffer.writeInt(contextStart); + buffer.writeInt(contextEnd); + buffer.writeFloat(x); + buffer.writeFloat(y); + buffer.writeBoolean(rtl); + } + + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Draw Operations", + id(), + CLASS_NAME) + .description("Draw a run of text, all in a single direction") + .field(INT, "textId", "id of bitmap") + .field(INT, "start", + "The start of the text to render. -1=end of string") + .field(INT, "end", + "The end of the text to render") + .field(INT, "contextStart", + "the index of the start of the shaping context") + .field(INT, "contextEnd", + "the index of the end of the shaping context") + .field(FLOAT, "x", + "The x position at which to draw the text") + .field(FLOAT, "y", + "The y position at which to draw the text") + .field(BOOLEAN, "RTL", + "Whether the run is in RTL direction"); + } + + @Override public void paint(PaintContext context) { - context.drawTextRun(mTextID, mStart, mEnd, mContextStart, mContextEnd, mX, mY, mRtl); + context.drawTextRun(mTextID, mStart, mEnd, mContextStart, + mContextEnd, mOutX, mOutY, mRtl); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextAnchored.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextAnchored.java index 4f0641f34d84..242bc2575cee 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextAnchored.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextAnchored.java @@ -15,7 +15,9 @@ */ package com.android.internal.widget.remotecompose.core.operations; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; @@ -23,6 +25,7 @@ import com.android.internal.widget.remotecompose.core.PaintOperation; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.VariableSupport; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import java.util.List; @@ -30,7 +33,8 @@ import java.util.List; * Draw Text in Anchored to a point */ public class DrawTextAnchored extends PaintOperation implements VariableSupport { - public static final Companion COMPANION = new Companion(); + private static final int OP_CODE = Operations.DRAW_TEXT_ANCHOR; + private static final String CLASS_NAME = "DrawTextAnchored"; int mTextID; float mX; float mY; @@ -91,7 +95,7 @@ public class DrawTextAnchored extends PaintOperation implements VariableSupport @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mTextID, mX, + apply(buffer, mTextID, mX, mY, mPanX, mPanY, @@ -113,64 +117,77 @@ public class DrawTextAnchored extends PaintOperation implements VariableSupport return Float.toString(v); } - public static class Companion implements CompanionOperation { - private Companion() { - } + public static void read(WireBuffer buffer, List<Operation> operations) { + int textID = buffer.readInt(); + float x = buffer.readFloat(); + float y = buffer.readFloat(); + float panX = buffer.readFloat(); + float panY = buffer.readFloat(); + int flags = buffer.readInt(); - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int textID = buffer.readInt(); - float x = buffer.readFloat(); - float y = buffer.readFloat(); - float panX = buffer.readFloat(); - float panY = buffer.readFloat(); - int flags = buffer.readInt(); - - DrawTextAnchored op = new DrawTextAnchored(textID, - x, y, - panX, panY, - flags); - - operations.add(op); - } + DrawTextAnchored op = new DrawTextAnchored(textID, + x, y, + panX, panY, + flags); - @Override - public String name() { - return ""; - } + operations.add(op); + } - @Override - public int id() { - return 0; - } + public static String name() { + return CLASS_NAME; + } - /** - * Writes out the operation to the buffer - * @param buffer - * @param textID - * @param x - * @param y - * @param panX - * @param panY - * @param flags - */ - public void apply(WireBuffer buffer, - int textID, - float x, - float y, - float panX, - float panY, - int flags) { - buffer.start(Operations.DRAW_TEXT_ANCHOR); - buffer.writeInt(textID); - buffer.writeFloat(x); - buffer.writeFloat(y); - buffer.writeFloat(panX); - buffer.writeFloat(panY); - buffer.writeInt(flags); - } + public static int id() { + return OP_CODE; + } + + /** + * Writes out the operation to the buffer + * + * @param buffer The buffer to write to + * @param textID The id of the text data + * @param x The x-position of the anchor point + * @param y The y-position of the anchor point + * @param panX The pan from left(-1) to right(1) 0 being centered + * @param panY The pan from top(-1) to bottom(1) 0 being centered + * @param flags Change the behaviour + */ + public static void apply(WireBuffer buffer, + int textID, + float x, + float y, + float panX, + float panY, + int flags) { + buffer.start(OP_CODE); + buffer.writeInt(textID); + buffer.writeFloat(x); + buffer.writeFloat(y); + buffer.writeFloat(panX); + buffer.writeFloat(panY); + buffer.writeInt(flags); } + public static void documentation(DocumentationBuilder doc) { + doc.operation("Draw Operations", + OP_CODE, + CLASS_NAME) + .description("Draw text centered about an anchor point") + .field(INT, "textId", "id of bitmap") + .field(FLOAT, "x", + "The x-position of the anchor point") + .field(FLOAT, "y", + "The y-position of the anchor point") + .field(FLOAT, "panX", + "The pan from left(-1) to right(1) 0 being centered") + .field(FLOAT, "panY", + "The pan from top(-1) to bottom(1) 0 being centered") + .field(INT, "flags", + "Change the behaviour"); + + } + + float[] mBounds = new float[4]; private float getHorizontalOffset() { @@ -194,8 +211,9 @@ public class DrawTextAnchored extends PaintOperation implements VariableSupport @Override public void paint(PaintContext context) { - context.getTextBounds(mTextID, 0, -1, - (mFlags & ANCHOR_MONOSPACE_MEASURE) != 0, mBounds); + int flags = ((mFlags & ANCHOR_MONOSPACE_MEASURE) != 0) + ? PaintContext.TEXT_MEASURE_MONOSPACE_WIDTH : 0; + context.getTextBounds(mTextID, 0, -1, flags, mBounds); float x = mOutX + getHorizontalOffset(); float y = (Float.isNaN(mOutPanY)) ? mOutY : mOutY + getVerticalOffset(); context.drawTextRun(mTextID, 0, -1, 0, 1, x, y, diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextOnPath.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextOnPath.java index b1a01724c315..d69362bd7a7d 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextOnPath.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextOnPath.java @@ -15,78 +15,117 @@ */ package com.android.internal.widget.remotecompose.core.operations; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; +import static com.android.internal.widget.remotecompose.core.operations.Utils.floatToString; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; import com.android.internal.widget.remotecompose.core.PaintOperation; +import com.android.internal.widget.remotecompose.core.RemoteContext; +import com.android.internal.widget.remotecompose.core.VariableSupport; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import java.util.List; /** * Draw text along a path. */ -public class DrawTextOnPath extends PaintOperation { - public static final Companion COMPANION = new Companion(); +public class DrawTextOnPath extends PaintOperation implements VariableSupport { + private static final int OP_CODE = Operations.DRAW_TEXT_ON_PATH; + private static final String CLASS_NAME = "DrawTextOnPath"; int mPathId; public int mTextId; float mVOffset; float mHOffset; + float mOutVOffset; + float mOutHOffset; public DrawTextOnPath(int textId, int pathId, float hOffset, float vOffset) { mPathId = pathId; mTextId = textId; - mHOffset = vOffset; - mVOffset = hOffset; + mOutHOffset = mHOffset = vOffset; + mOutVOffset = mVOffset = hOffset; + } + + + @Override + public void updateVariables(RemoteContext context) { + mOutHOffset = (Float.isNaN(mHOffset)) + ? context.getFloat(Utils.idFromNan(mHOffset)) : mHOffset; + mOutVOffset = (Float.isNaN(mVOffset)) + ? context.getFloat(Utils.idFromNan(mVOffset)) : mVOffset; + + } + + @Override + public void registerListening(RemoteContext context) { + if (Float.isNaN(mHOffset)) { + context.listensTo(Utils.idFromNan(mHOffset), this); + } + if (Float.isNaN(mVOffset)) { + context.listensTo(Utils.idFromNan(mVOffset), this); + } } @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mTextId, mPathId, mHOffset, mVOffset); + apply(buffer, mTextId, mPathId, mHOffset, mVOffset); } @Override public String toString() { return "DrawTextOnPath [" + mTextId + "] [" + mPathId + "] " - + mHOffset + ", " + mVOffset; + + floatToString(mHOffset, mOutHOffset) + ", " + + floatToString(mVOffset, mOutVOffset); } - public static class Companion implements CompanionOperation { - private Companion() { - } + public static void read(WireBuffer buffer, List<Operation> operations) { + int textId = buffer.readInt(); + int pathId = buffer.readInt(); + float hOffset = buffer.readFloat(); + float vOffset = buffer.readFloat(); + DrawTextOnPath op = new DrawTextOnPath(textId, pathId, hOffset, vOffset); + operations.add(op); + } - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int textId = buffer.readInt(); - int pathId = buffer.readInt(); - float hOffset = buffer.readFloat(); - float vOffset = buffer.readFloat(); - DrawTextOnPath op = new DrawTextOnPath(textId, pathId, hOffset, vOffset); - operations.add(op); - } + public static String name() { + return "DrawTextOnPath"; + } - @Override - public String name() { - return "DrawTextOnPath"; - } - @Override - public int id() { - return Operations.DRAW_TEXT_ON_PATH; - } + public static int id() { + return Operations.DRAW_TEXT_ON_PATH; + } - public void apply(WireBuffer buffer, int textId, int pathId, float hOffset, float vOffset) { - buffer.start(Operations.DRAW_TEXT_ON_PATH); - buffer.writeInt(textId); - buffer.writeInt(pathId); - buffer.writeFloat(hOffset); - buffer.writeFloat(vOffset); - } + public static void apply(WireBuffer buffer, int textId, int pathId, + float hOffset, float vOffset) { + buffer.start(OP_CODE); + buffer.writeInt(textId); + buffer.writeInt(pathId); + buffer.writeFloat(hOffset); + buffer.writeFloat(vOffset); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Draw Operations", + OP_CODE, + CLASS_NAME) + .description("Draw text along path object") + .field(INT, "textId", + "id of the text") + .field(INT, "pathId", + "id of the path") + .field(FLOAT, "xOffset", + "x Shift of the text") + .field(FLOAT, "yOffset", + "y Shift of the text"); } @Override public void paint(PaintContext context) { - context.drawTextOnPath(mTextId, mPathId, mHOffset, mVOffset); + context.drawTextOnPath(mTextId, mPathId, mOutHOffset, mOutVOffset); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTweenPath.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTweenPath.java index 48fc94ee5f27..354726319c45 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTweenPath.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTweenPath.java @@ -15,20 +15,30 @@ */ package com.android.internal.widget.remotecompose.core.operations; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; +import static com.android.internal.widget.remotecompose.core.operations.Utils.floatToString; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; import com.android.internal.widget.remotecompose.core.PaintOperation; +import com.android.internal.widget.remotecompose.core.RemoteContext; +import com.android.internal.widget.remotecompose.core.VariableSupport; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import java.util.List; -public class DrawTweenPath extends PaintOperation { - public static final Companion COMPANION = new Companion(); +public class DrawTweenPath extends PaintOperation implements VariableSupport { + private static final int OP_CODE = Operations.DRAW_TWEEN_PATH; + private static final String CLASS_NAME = "DrawTweenPath"; float mTween; float mStart; float mStop; + float mOutTween; + float mOutStart; + float mOutStop; int mPath1Id; int mPath2Id; @@ -38,16 +48,39 @@ public class DrawTweenPath extends PaintOperation { float tween, float start, float stop) { - mTween = tween; - mStart = start; - mStop = stop; + mOutTween = mTween = tween; + mOutStart = mStart = start; + mOutStop = mStop = stop; mPath1Id = path1Id; mPath2Id = path2Id; } @Override + public void updateVariables(RemoteContext context) { + mOutTween = (Float.isNaN(mTween)) + ? context.getFloat(Utils.idFromNan(mTween)) : mTween; + mOutStart = (Float.isNaN(mStart)) + ? context.getFloat(Utils.idFromNan(mStart)) : mStart; + mOutStop = (Float.isNaN(mStop)) + ? context.getFloat(Utils.idFromNan(mStop)) : mStop; + } + + @Override + public void registerListening(RemoteContext context) { + if (Float.isNaN(mTween)) { + context.listensTo(Utils.idFromNan(mTween), this); + } + if (Float.isNaN(mStart)) { + context.listensTo(Utils.idFromNan(mStart), this); + } + if (Float.isNaN(mStop)) { + context.listensTo(Utils.idFromNan(mStop), this); + } + } + + @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mPath1Id, + apply(buffer, mPath1Id, mPath2Id, mTween, mStart, @@ -57,58 +90,74 @@ public class DrawTweenPath extends PaintOperation { @Override public String toString() { return "DrawTweenPath " + mPath1Id + " " + mPath2Id - + " " + mTween + " " + mStart + " " - + "- " + mStop; + + " " + floatToString(mTween, mOutTween) + " " + + floatToString(mStart, mOutStart) + " " + + "- " + floatToString(mStop, mOutStop); } - public static class Companion implements CompanionOperation { - private Companion() { - } - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int path1Id = buffer.readInt(); - int path2Id = buffer.readInt(); - float tween = buffer.readFloat(); - float start = buffer.readFloat(); - float stop = buffer.readFloat(); - DrawTweenPath op = new DrawTweenPath(path1Id, path2Id, - tween, start, stop); - operations.add(op); - } + public static void read(WireBuffer buffer, List<Operation> operations) { + int path1Id = buffer.readInt(); + int path2Id = buffer.readInt(); + float tween = buffer.readFloat(); + float start = buffer.readFloat(); + float stop = buffer.readFloat(); + DrawTweenPath op = new DrawTweenPath(path1Id, path2Id, + tween, start, stop); + operations.add(op); + } - @Override - public String name() { - return "DrawTweenPath"; - } - @Override - public int id() { - return Operations.DRAW_TWEEN_PATH; - } + public static String name() { + return "DrawTweenPath"; + } + + + public static int id() { + return Operations.DRAW_TWEEN_PATH; + } + + public static void apply(WireBuffer buffer, + int path1Id, + int path2Id, + float tween, + float start, + float stop) { + buffer.start(OP_CODE); + buffer.writeInt(path1Id); + buffer.writeInt(path2Id); + buffer.writeFloat(tween); + buffer.writeFloat(start); + buffer.writeFloat(stop); + } + + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Draw Operations", + OP_CODE, + CLASS_NAME) + .description("Draw text along path object") + .field(INT, "pathId1", + "id of path 1") + .field(INT, "pathId2", + "id of path 2") + .field(FLOAT, "tween", + "interpolate between the two paths") + .field(FLOAT, "start", + "trim the start of the path") + .field(FLOAT, "yOffset", + "trim the end of the path"); - public void apply(WireBuffer buffer, - int path1Id, - int path2Id, - float tween, - float start, - float stop) { - buffer.start(Operations.DRAW_TWEEN_PATH); - buffer.writeInt(path1Id); - buffer.writeInt(path2Id); - buffer.writeFloat(tween); - buffer.writeFloat(start); - buffer.writeFloat(stop); - } } + @Override public void paint(PaintContext context) { context.drawTweenPath(mPath1Id, mPath2Id, - mTween, - mStart, - mStop); + mOutTween, + mOutStart, + mOutStop); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/FloatConstant.java b/core/java/com/android/internal/widget/remotecompose/core/operations/FloatConstant.java index 576b53f9fc6c..31b8ff6db58b 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/FloatConstant.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/FloatConstant.java @@ -15,11 +15,14 @@ */ package com.android.internal.widget.remotecompose.core.operations; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import java.util.List; @@ -27,10 +30,10 @@ import java.util.List; * Operation to deal with Text data */ public class FloatConstant implements Operation { + private static final int OP_CODE = Operations.DATA_FLOAT; + private static final String CLASS_NAME = "FloatConstant"; public int mTextId; public float mValue; - public static final Companion COMPANION = new Companion(); - public static final int MAX_STRING_SIZE = 4000; public FloatConstant(int textId, float value) { this.mTextId = textId; @@ -39,46 +42,52 @@ public class FloatConstant implements Operation { @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mTextId, mValue); + apply(buffer, mTextId, mValue); } @Override public String toString() { - return "FloatConstant[" + mTextId + "] = " + mValue + ""; + return "FloatConstant[" + mTextId + "] = " + mValue; + } + + public static String name() { + return CLASS_NAME; + } + + + public static int id() { + return OP_CODE; } - public static class Companion implements CompanionOperation { - private Companion() {} - - @Override - public String name() { - return "FloatExpression"; - } - - @Override - public int id() { - return Operations.DATA_FLOAT; - } - - /** - * Writes out the operation to the buffer - * @param buffer - * @param textId - * @param value - */ - public void apply(WireBuffer buffer, int textId, float value) { - buffer.start(Operations.DATA_FLOAT); - buffer.writeInt(textId); - buffer.writeFloat(value); - } - - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int textId = buffer.readInt(); - - float value = buffer.readFloat(); - operations.add(new FloatConstant(textId, value)); - } + /** + * Writes out the operation to the buffer + * + * @param buffer write command to this buffer + * @param id the id + * @param value the value of the float + */ + public static void apply(WireBuffer buffer, int id, float value) { + buffer.start(OP_CODE); + buffer.writeInt(id); + buffer.writeFloat(value); + } + + public static void read(WireBuffer buffer, List<Operation> operations) { + int textId = buffer.readInt(); + + float value = buffer.readFloat(); + operations.add(new FloatConstant(textId, value)); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Expressions Operations", + OP_CODE, + CLASS_NAME) + .description("A float and its associated id") + .field(INT, "id", "id of float") + .field(FLOAT, "value", + "32-bit float value"); + } @Override diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/FloatExpression.java b/core/java/com/android/internal/widget/remotecompose/core/operations/FloatExpression.java index 354f41b813e0..e3df1eb0da26 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/FloatExpression.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/FloatExpression.java @@ -15,13 +15,19 @@ */ package com.android.internal.widget.remotecompose.core.operations; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT_ARRAY; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.SHORT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.VariableSupport; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import com.android.internal.widget.remotecompose.core.operations.utilities.AnimatedFloatExpression; +import com.android.internal.widget.remotecompose.core.operations.utilities.NanMap; import com.android.internal.widget.remotecompose.core.operations.utilities.easing.FloatAnimation; import java.util.Arrays; @@ -35,6 +41,8 @@ import java.util.List; * The floats represent a RPN style calculator */ public class FloatExpression implements Operation, VariableSupport { + private static final int OP_CODE = Operations.ANIMATED_FLOAT; + private static final String CLASS_NAME = "FloatExpression"; public int mId; public float[] mSrcValue; public float[] mSrcAnimation; @@ -42,8 +50,7 @@ public class FloatExpression implements Operation, VariableSupport { public float[] mPreCalcValue; private float mLastChange = Float.NaN; AnimatedFloatExpression mExp = new AnimatedFloatExpression(); - public static final Companion COMPANION = new Companion(); - public static final int MAX_STRING_SIZE = 4000; + public static final int MAX_EXPRESSION_SIZE = 32; public FloatExpression(int id, float[] value, float[] animation) { this.mId = id; @@ -59,11 +66,12 @@ public class FloatExpression implements Operation, VariableSupport { if (mPreCalcValue == null || mPreCalcValue.length != mSrcValue.length) { mPreCalcValue = new float[mSrcValue.length]; } - //Utils.log("updateVariables "); + boolean value_changed = false; for (int i = 0; i < mSrcValue.length; i++) { float v = mSrcValue[i]; - if (Float.isNaN(v) && !AnimatedFloatExpression.isMathOperator(v)) { + if (Float.isNaN(v) && !AnimatedFloatExpression.isMathOperator(v) + && !NanMap.isDataVariable(v)) { float newValue = context.getFloat(Utils.idFromNan(v)); if (mFloatAnimation != null) { if (mPreCalcValue[i] != newValue) { @@ -91,9 +99,9 @@ public class FloatExpression implements Operation, VariableSupport { @Override public void registerListening(RemoteContext context) { - for (int i = 0; i < mSrcValue.length; i++) { - float v = mSrcValue[i]; - if (Float.isNaN(v) && !AnimatedFloatExpression.isMathOperator(v)) { + for (float v : mSrcValue) { + if (Float.isNaN(v) && !AnimatedFloatExpression.isMathOperator(v) + && !NanMap.isDataVariable(v)) { context.listensTo(Utils.idFromNan(v), this); } } @@ -110,13 +118,14 @@ public class FloatExpression implements Operation, VariableSupport { float f = mFloatAnimation.get(t - mLastChange); context.loadFloat(mId, f); } else { - context.loadFloat(mId, mExp.eval(Arrays.copyOf(mPreCalcValue, mPreCalcValue.length))); + context.loadFloat(mId, mExp.eval(context.getCollectionsAccess(), + Arrays.copyOf(mPreCalcValue, mPreCalcValue.length))); } } @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mId, mSrcValue, mSrcAnimation); + apply(buffer, mId, mSrcValue, mSrcAnimation); } @Override @@ -124,78 +133,96 @@ public class FloatExpression implements Operation, VariableSupport { String[] labels = new String[mSrcValue.length]; for (int i = 0; i < mSrcValue.length; i++) { if (Float.isNaN(mSrcValue[i])) { - labels[i] = "[" + Utils.idFromNan(mSrcValue[i]) + "]"; + labels[i] = "[" + Utils.idStringFromNan(mSrcValue[i]) + "]"; } - + } + if (mPreCalcValue == null) { + return "FloatExpression[" + mId + "] = (" + + AnimatedFloatExpression.toString(mSrcValue, labels) + ")"; } return "FloatExpression[" + mId + "] = (" + AnimatedFloatExpression.toString(mPreCalcValue, labels) + ")"; } - public static class Companion implements CompanionOperation { - private Companion() { - } + public static String name() { + return CLASS_NAME; + } - @Override - public String name() { - return "FloatExpression"; - } + public static int id() { + return OP_CODE; + } - @Override - public int id() { - return Operations.ANIMATED_FLOAT; + /** + * Writes out the operation to the buffer + * + * @param buffer The buffer to write to + * @param id the id of the resulting float + * @param value the float expression array + * @param animation the animation expression array + */ + public static void apply(WireBuffer buffer, int id, float[] value, float[] animation) { + buffer.start(OP_CODE); + buffer.writeInt(id); + + int len = value.length; + if (animation != null) { + len |= (animation.length << 16); } + buffer.writeInt(len); - /** - * Writes out the operation to the buffer - * @param buffer - * @param id - * @param value - * @param animation - */ - public void apply(WireBuffer buffer, int id, float[] value, float[] animation) { - buffer.start(Operations.ANIMATED_FLOAT); - buffer.writeInt(id); - - int len = value.length; - if (animation != null) { - len |= (animation.length << 16); + for (float v : value) { + buffer.writeFloat(v); + } + if (animation != null) { + for (float v : animation) { + buffer.writeFloat(v); } - buffer.writeInt(len); + } - for (int i = 0; i < value.length; i++) { - buffer.writeFloat(value[i]); - } - if (animation != null) { - for (int i = 0; i < animation.length; i++) { - buffer.writeFloat(animation[i]); - } - } + } + public static void read(WireBuffer buffer, List<Operation> operations) { + int id = buffer.readInt(); + int len = buffer.readInt(); + int valueLen = len & 0xFFFF; + if (valueLen > MAX_EXPRESSION_SIZE) { + throw new RuntimeException("Float expression to long"); + } + int animLen = (len >> 16) & 0xFFFF; + float[] values = new float[valueLen]; + for (int i = 0; i < values.length; i++) { + values[i] = buffer.readFloat(); } - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int id = buffer.readInt(); - int len = buffer.readInt(); - int valueLen = len & 0xFFFF; - int animLen = (len >> 16) & 0xFFFF; - float[] values = new float[valueLen]; - for (int i = 0; i < values.length; i++) { - values[i] = buffer.readFloat(); - } - - float[] animation; - if (animLen != 0) { - animation = new float[animLen]; - for (int i = 0; i < animation.length; i++) { - animation[i] = buffer.readFloat(); - } - } else { - animation = null; + float[] animation; + if (animLen != 0) { + animation = new float[animLen]; + for (int i = 0; i < animation.length; i++) { + animation[i] = buffer.readFloat(); } - operations.add(new FloatExpression(id, values, animation)); + } else { + animation = null; } + operations.add(new FloatExpression(id, values, animation)); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Expressions Operations", + OP_CODE, + CLASS_NAME) + .description("A Float expression") + .field(INT, "id", "The id of the Color") + .field(SHORT, "expression_length", "expression length") + .field(SHORT, "animation_length", "animation description length") + .field(FLOAT_ARRAY, "expression", "expression_length", + "Sequence of Floats representing and expression") + .field(FLOAT_ARRAY, "AnimationSpec", "animation_length", + "Sequence of Floats representing animation curve") + .field(FLOAT, "duration", "> time in sec") + .field(INT, "bits", "> WRAP|INITALVALUE | TYPE ") + .field(FLOAT_ARRAY, "spec", "> [SPEC PARAMETERS] ") + .field(FLOAT, "initialValue", "> [Initial value] ") + .field(FLOAT, "wrapValue", "> [Wrap value] "); } @Override diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/Header.java b/core/java/com/android/internal/widget/remotecompose/core/operations/Header.java index 9a1f37b22de5..099bce886b22 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/Header.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/Header.java @@ -24,7 +24,6 @@ import com.android.internal.widget.remotecompose.core.RemoteComposeOperation; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.WireBuffer; import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; -import com.android.internal.widget.remotecompose.core.documentation.DocumentedCompanionOperation; import java.util.List; @@ -35,6 +34,8 @@ import java.util.List; * as the dimensions of the document in pixels. */ public class Header implements RemoteComposeOperation { + private static final int OP_CODE = Operations.HEADER; + private static final String CLASS_NAME = "Header"; public static final int MAJOR_VERSION = 0; public static final int MINOR_VERSION = 1; public static final int PATCH_VERSION = 0; @@ -49,7 +50,6 @@ public class Header implements RemoteComposeOperation { float mDensity; long mCapabilities; - public static final Companion COMPANION = new Companion(); /** * It encodes the version of the document (following semantic versioning) as well @@ -76,7 +76,7 @@ public class Header implements RemoteComposeOperation { @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mWidth, mHeight, mDensity, mCapabilities); + apply(buffer, mWidth, mHeight, mDensity, mCapabilities); } @Override @@ -96,59 +96,51 @@ public class Header implements RemoteComposeOperation { return toString(); } - public static class Companion implements DocumentedCompanionOperation { - private Companion() { - } - - @Override - public String name() { - return "Header"; - } - - @Override - public int id() { - return Operations.HEADER; - } - - public void apply(WireBuffer buffer, int width, int height, - float density, long capabilities) { - buffer.start(Operations.HEADER); - buffer.writeInt(MAJOR_VERSION); // major version number of the protocol - buffer.writeInt(MINOR_VERSION); // minor version number of the protocol - buffer.writeInt(PATCH_VERSION); // patch version number of the protocol - buffer.writeInt(width); - buffer.writeInt(height); - // buffer.writeFloat(density); - buffer.writeLong(capabilities); - } - - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int majorVersion = buffer.readInt(); - int minorVersion = buffer.readInt(); - int patchVersion = buffer.readInt(); - int width = buffer.readInt(); - int height = buffer.readInt(); - // float density = buffer.readFloat(); - float density = 1f; - long capabilities = buffer.readLong(); - Header header = new Header(majorVersion, minorVersion, patchVersion, - width, height, density, capabilities); - operations.add(header); - } - - @Override - public void documentation(DocumentationBuilder doc) { - doc.operation("Protocol Operations", id(), name()) - .description("Document metadata, containing the version," - + " original size & density, capabilities mask") - .field(INT, "MAJOR_VERSION", "Major version") - .field(INT, "MINOR_VERSION", "Minor version") - .field(INT, "PATCH_VERSION", "Patch version") - .field(INT, "WIDTH", "Major version") - .field(INT, "HEIGHT", "Major version") - // .field(FLOAT, "DENSITY", "Major version") - .field(LONG, "CAPABILITIES", "Major version"); - } + public static String name() { + return CLASS_NAME; } + + public static int id() { + return OP_CODE; + } + + public static void apply(WireBuffer buffer, int width, int height, + float density, long capabilities) { + buffer.start(OP_CODE); + buffer.writeInt(MAJOR_VERSION); // major version number of the protocol + buffer.writeInt(MINOR_VERSION); // minor version number of the protocol + buffer.writeInt(PATCH_VERSION); // patch version number of the protocol + buffer.writeInt(width); + buffer.writeInt(height); + // buffer.writeFloat(density); TODO fix or remove + buffer.writeLong(capabilities); + } + + public static void read(WireBuffer buffer, List<Operation> operations) { + int majorVersion = buffer.readInt(); + int minorVersion = buffer.readInt(); + int patchVersion = buffer.readInt(); + int width = buffer.readInt(); + int height = buffer.readInt(); + // float density = buffer.readFloat(); + float density = 1f; + long capabilities = buffer.readLong(); + Header header = new Header(majorVersion, minorVersion, patchVersion, + width, height, density, capabilities); + operations.add(header); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Protocol Operations", OP_CODE, CLASS_NAME) + .description("Document metadata, containing the version," + + " original size & density, capabilities mask") + .field(INT, "MAJOR_VERSION", "Major version") + .field(INT, "MINOR_VERSION", "Minor version") + .field(INT, "PATCH_VERSION", "Patch version") + .field(INT, "WIDTH", "Major version") + .field(INT, "HEIGHT", "Major version") + // .field(FLOAT, "DENSITY", "Major version") + .field(LONG, "CAPABILITIES", "Major version"); + } + } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/IntegerExpression.java b/core/java/com/android/internal/widget/remotecompose/core/operations/IntegerExpression.java index d52df5d2bcea..11730f358eaf 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/IntegerExpression.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/IntegerExpression.java @@ -15,12 +15,15 @@ */ package com.android.internal.widget.remotecompose.core.operations; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT_ARRAY; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.VariableSupport; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import com.android.internal.widget.remotecompose.core.operations.utilities.IntegerExpressionEvaluator; import java.util.Arrays; @@ -34,13 +37,14 @@ import java.util.List; * The floats represent a RPN style calculator */ public class IntegerExpression implements Operation, VariableSupport { + private static final int OP_CODE = Operations.INTEGER_EXPRESSION; + private static final String CLASS_NAME = "IntegerExpression"; public int mId; private int mMask; private int mPreMask; public int[] mSrcValue; public int[] mPreCalcValue; private float mLastChange = Float.NaN; - public static final Companion COMPANION = new Companion(); public static final int MAX_STRING_SIZE = 4000; IntegerExpressionEvaluator mExp = new IntegerExpressionEvaluator(); @@ -89,7 +93,7 @@ public class IntegerExpression implements Operation, VariableSupport { @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mId, mMask, mSrcValue); + apply(buffer, mId, mMask, mSrcValue); } @Override @@ -112,51 +116,57 @@ public class IntegerExpression implements Operation, VariableSupport { return "IntegerExpression[" + mId + "] = (" + s + ")"; } - public static class Companion implements CompanionOperation { - private Companion() { - } + public static String name() { + return CLASS_NAME; + } - @Override - public String name() { - return "FloatExpression"; - } + public static int id() { + return OP_CODE; + } - @Override - public int id() { - return Operations.INTEGER_EXPRESSION; + /** + * Writes out the operation to the buffer + * + * @param buffer buffer to write to + * @param id the id of the integer + * @param mask the mask bits of ints & operators or variables + * @param value array of integers to be evaluated + */ + public static void apply(WireBuffer buffer, int id, int mask, int[] value) { + buffer.start(OP_CODE); + buffer.writeInt(id); + buffer.writeInt(mask); + buffer.writeInt(value.length); + for (int opMask : value) { + buffer.writeInt(opMask); } + } - /** - * Writes out the operation to the buffer - * - * @param buffer - * @param id - * @param mask - * @param value - */ - public void apply(WireBuffer buffer, int id, int mask, int[] value) { - buffer.start(Operations.INTEGER_EXPRESSION); - buffer.writeInt(id); - buffer.writeInt(mask); - buffer.writeInt(value.length); - for (int i = 0; i < value.length; i++) { - buffer.writeInt(value[i]); - } - } + public static void read(WireBuffer buffer, List<Operation> operations) { + int id = buffer.readInt(); + int mask = buffer.readInt(); + int len = buffer.readInt(); - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int id = buffer.readInt(); - int mask = buffer.readInt(); - int len = buffer.readInt(); + int[] values = new int[len]; + for (int i = 0; i < values.length; i++) { + values[i] = buffer.readInt(); + } - int[] values = new int[len]; - for (int i = 0; i < values.length; i++) { - values[i] = buffer.readInt(); - } + operations.add(new IntegerExpression(id, mask, values)); + } - operations.add(new IntegerExpression(id, mask, values)); - } + public static void documentation(DocumentationBuilder doc) { + doc.operation("Data Operations", + OP_CODE, + CLASS_NAME) + .description("Expression that computes an integer") + .field(INT, "id", "id of integer") + .field(INT, "mask", + "bits representing operators or other id's") + .field(INT, "length", + "length of array") + .field(INT_ARRAY, "values", "length", + "Array of ints"); } @Override @@ -166,8 +176,9 @@ public class IntegerExpression implements Operation, VariableSupport { /** * given the "i" position in the mask is this an ID - * @param mask 32 bit mask used for defining numbers vs other - * @param i the bit in question + * + * @param mask 32 bit mask used for defining numbers vs other + * @param i the bit in question * @param value the value * @return true if this is an ID */ diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRestore.java b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRestore.java index 0dad45ce356b..f3f9a5142a24 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRestore.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRestore.java @@ -15,24 +15,30 @@ */ package com.android.internal.widget.remotecompose.core.operations; -import com.android.internal.widget.remotecompose.core.CompanionOperation; import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; import com.android.internal.widget.remotecompose.core.PaintOperation; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import java.util.List; public class MatrixRestore extends PaintOperation { - public static final Companion COMPANION = new Companion(); - + private static final int OP_CODE = Operations.MATRIX_RESTORE; + private static final String CLASS_NAME = "MatrixRestore"; public MatrixRestore() { } @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer); + apply(buffer); + } + + + public static void read(WireBuffer buffer, List<Operation> operations) { + MatrixRestore op = new MatrixRestore(); + operations.add(op); } @Override @@ -40,32 +46,28 @@ public class MatrixRestore extends PaintOperation { return "MatrixRestore"; } - public static class Companion implements CompanionOperation { - private Companion() { - } - @Override - public void read(WireBuffer buffer, List<Operation> operations) { + public static String name() { + return CLASS_NAME; + } - MatrixRestore op = new MatrixRestore(); - operations.add(op); - } - @Override - public String name() { - return "MatrixRestore"; - } + public static int id() { + return OP_CODE; + } - @Override - public int id() { - return Operations.MATRIX_RESTORE; - } + public static void apply(WireBuffer buffer) { + buffer.start(OP_CODE); + } - public void apply(WireBuffer buffer) { - buffer.start(Operations.MATRIX_RESTORE); - } + public static void documentation(DocumentationBuilder doc) { + doc.operation("Canvas Operations", + OP_CODE, + CLASS_NAME) + .description("Restore the matrix and clip"); } + @Override public void paint(PaintContext context) { context.matrixRestore(); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRotate.java b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRotate.java index bbf41351a1c5..9cc82fc05e69 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRotate.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRotate.java @@ -15,29 +15,81 @@ */ package com.android.internal.widget.remotecompose.core.operations; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; + +import java.util.List; public class MatrixRotate extends DrawBase3 { - public static final Companion COMPANION = - new Companion(Operations.MATRIX_ROTATE) { - @Override - public Operation construct(float rotate, - float pivotX, - float pivotY - ) { - return new MatrixRotate(rotate, pivotX, pivotY); - } - }; + public static final int OP_CODE = Operations.MATRIX_ROTATE; + private static final String CLASS_NAME = "MatrixRotate"; + + public static void read(WireBuffer buffer, List<Operation> operations) { + Maker m = new Maker() { + @Override + public DrawBase3 create(float v1, float v2, float v3) { + return new MatrixRotate(v1, v2, v3); + } + }; + read(m, buffer, operations); + } + + public static int id() { + return OP_CODE; + } + + public static String name() { + return CLASS_NAME; + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Canvas Operations", + OP_CODE, + CLASS_NAME) + .description("apply rotation to matrix") + .field(FLOAT, "rotate", "Angle to rotate") + .field(FLOAT, "pivotX", "X Pivot point") + .field(FLOAT, "pivotY", "Y Pivot point"); + } + + + protected void write(WireBuffer buffer, + float v1, + float v2, + float v3) { + apply(buffer, v1, v2, v3); + } public MatrixRotate(float rotate, float pivotX, float pivotY) { super(rotate, pivotX, pivotY); - mName = "MatrixRotate"; + mName = CLASS_NAME; } @Override public void paint(PaintContext context) { context.matrixRotate(mV1, mV2, mV3); } + + /** + * Writes out the operation to the buffer + * + * @param buffer The buffer to write into + * @param x1 Angle to rotate + * @param y1 X Pivot point + * @param x2 Y Pivot point + */ + public static void apply(WireBuffer buffer, + float x1, + float y1, + float x2) { + buffer.start(OP_CODE); + buffer.writeFloat(x1); + buffer.writeFloat(y1); + buffer.writeFloat(x2); + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSave.java b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSave.java index d3d5bfba8992..a47ed6b9f99a 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSave.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSave.java @@ -15,25 +15,22 @@ */ package com.android.internal.widget.remotecompose.core.operations; -import com.android.internal.widget.remotecompose.core.CompanionOperation; import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; import com.android.internal.widget.remotecompose.core.PaintOperation; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import java.util.List; public class MatrixSave extends PaintOperation { - public static final Companion COMPANION = new Companion(); - - public MatrixSave() { - - } + private static final int OP_CODE = Operations.MATRIX_SAVE; + private static final String CLASS_NAME = "MatrixSave"; @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer); + apply(buffer); } @Override @@ -41,30 +38,29 @@ public class MatrixSave extends PaintOperation { return "MatrixSave;"; } - public static class Companion implements CompanionOperation { - private Companion() { - } + public static void read(WireBuffer buffer, List<Operation> operations) { + MatrixSave op = new MatrixSave(); + operations.add(op); + } - @Override - public void read(WireBuffer buffer, List<Operation> operations) { + public static String name() { + return CLASS_NAME; + } - MatrixSave op = new MatrixSave(); - operations.add(op); - } - @Override - public String name() { - return "Matrix"; - } + public static int id() { + return OP_CODE; + } - @Override - public int id() { - return Operations.MATRIX_SAVE; - } + public static void apply(WireBuffer buffer) { + buffer.start(Operations.MATRIX_SAVE); + } - public void apply(WireBuffer buffer) { - buffer.start(Operations.MATRIX_SAVE); - } + public static void documentation(DocumentationBuilder doc) { + doc.operation("Canvas Operations", + OP_CODE, + CLASS_NAME) + .description("Save the matrix and clip to a stack"); } @Override diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixScale.java b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixScale.java index 04b940ba16c8..769e798eb6b2 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixScale.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixScale.java @@ -15,30 +15,81 @@ */ package com.android.internal.widget.remotecompose.core.operations; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; + +import java.util.List; public class MatrixScale extends DrawBase4 { - public static final Companion COMPANION = - new Companion(Operations.MATRIX_SCALE) { - @Override - public Operation construct(float scaleX, - float scaleY, - float centerX, - float centerY - ) { - return new MatrixScale(scaleX, scaleY, centerX, centerY); - } - }; + public static final int OP_CODE = Operations.MATRIX_SCALE; + public static final String CLASS_NAME = "MatrixScale"; + + public static void read(WireBuffer buffer, List<Operation> operations) { + Maker m = MatrixScale::new; + read(m, buffer, operations); + } + + public static int id() { + return OP_CODE; + } + + public static String name() { + return CLASS_NAME; + } + + + protected void write(WireBuffer buffer, + float v1, + float v2, + float v3, + float v4) { + apply(buffer, v1, v2, v3, v4); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Canvas Operations", + OP_CODE, + CLASS_NAME) + .description("Draw the specified Oval") + .field(FLOAT, "scaleX", + "The amount to scale in X") + .field(FLOAT, "scaleY", + "The amount to scale in Y") + .field(FLOAT, "pivotX", + "The x-coordinate for the pivot point") + .field(FLOAT, "pivotY", + "The y-coordinate for the pivot point"); + } public MatrixScale(float scaleX, float scaleY, float centerX, float centerY) { super(scaleX, scaleY, centerX, centerY); - mName = "MatrixScale"; + mName = CLASS_NAME; } @Override public void paint(PaintContext context) { context.matrixScale(mX1, mY1, mX2, mY2); } + + /** + * Writes out the DrawOval to the buffer + * + * @param buffer buffer to write to + * @param x1 start x of DrawOval + * @param y1 start y of the DrawOval + * @param x2 end x of the DrawOval + * @param y2 end y of the DrawOval + */ + public static void apply(WireBuffer buffer, + float x1, + float y1, + float x2, + float y2) { + write(buffer, OP_CODE, x1, y1, x2, y2); + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSkew.java b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSkew.java index a3888997c758..34f71b4d1a91 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSkew.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSkew.java @@ -15,65 +15,74 @@ */ package com.android.internal.widget.remotecompose.core.operations; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; -import com.android.internal.widget.remotecompose.core.PaintOperation; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import java.util.List; -public class MatrixSkew extends PaintOperation { - public static final Companion COMPANION = new Companion(); - float mSkewX, mSkewY; +public class MatrixSkew extends DrawBase2 { + public static final int OP_CODE = Operations.MATRIX_SKEW; + public static final String CLASS_NAME = "MatrixSkew"; - public MatrixSkew(float skewX, float skewY) { - mSkewX = skewX; - mSkewY = skewY; + + public static void read(WireBuffer buffer, List<Operation> operations) { + Maker m = MatrixSkew::new; + read(m, buffer, operations); } - @Override - public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mSkewX, mSkewY); + public static int id() { + return OP_CODE; } - @Override - public String toString() { - return "DrawArc " + mSkewY + ", " + mSkewY + ";"; + public static String name() { + return CLASS_NAME; } - public static class Companion implements CompanionOperation { - private Companion() { - } - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - float skewX = buffer.readFloat(); - float skewY = buffer.readFloat(); - MatrixSkew op = new MatrixSkew(skewX, skewY); - operations.add(op); - } + protected void write(WireBuffer buffer, + float v1, + float v2) { + apply(buffer, v1, v2); + } - @Override - public String name() { - return "Matrix"; - } + public static void documentation(DocumentationBuilder doc) { + doc.operation("Canvas Operations", + OP_CODE, + CLASS_NAME) + .description("Current matrix with the specified skew.") + .field(FLOAT, "skewX", + "The amount to skew in X") + .field(FLOAT, "skewY", + "The amount to skew in Y"); + } - @Override - public int id() { - return Operations.MATRIX_SKEW; - } - public void apply(WireBuffer buffer, float skewX, float skewY) { - buffer.start(Operations.MATRIX_SKEW); - buffer.writeFloat(skewX); - buffer.writeFloat(skewY); - } + public MatrixSkew(float skewX, float skewY) { + super(skewX, skewY); + mName = CLASS_NAME; } @Override public void paint(PaintContext context) { - context.matrixSkew(mSkewX, mSkewY); + context.matrixSkew(mV1, mV2); + } + + /** + * Writes out the DrawOval to the buffer + * + * @param buffer buffer to write to + * @param x1 start x of DrawOval + * @param y1 start y of the DrawOval + */ + public static void apply(WireBuffer buffer, + float x1, + float y1 + ) { + write(buffer, OP_CODE, x1, y1); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixTranslate.java b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixTranslate.java index 4f34e987e064..8561343c0015 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixTranslate.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixTranslate.java @@ -15,28 +15,71 @@ */ package com.android.internal.widget.remotecompose.core.operations; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; + +import java.util.List; public class MatrixTranslate extends DrawBase2 { - public static final Companion COMPANION = - new Companion(Operations.MATRIX_TRANSLATE) { - @Override - public Operation construct(float x1, - float y1 - ) { - return new MatrixTranslate(x1, y1); - } - }; + public static final int OP_CODE = Operations.MATRIX_TRANSLATE; + public static final String CLASS_NAME = "MatrixTranslate"; + + public static void read(WireBuffer buffer, List<Operation> operations) { + Maker m = MatrixTranslate::new; + read(m, buffer, operations); + } + + public static int id() { + return OP_CODE; + } + + public static String name() { + return CLASS_NAME; + } + + protected void write(WireBuffer buffer, + float v1, + float v2) { + apply(buffer, v1, v2); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Canvas Operations", + OP_CODE, + "MatrixTranslate") + .description("Preconcat the current matrix with the specified translation") + .field(FLOAT, "dx", + "The distance to translate in X") + .field(FLOAT, "dy", + "The distance to translate in Y"); + + } public MatrixTranslate(float translateX, float translateY) { super(translateX, translateY); - mName = "MatrixTranslate"; + mName = CLASS_NAME; } @Override public void paint(PaintContext context) { context.matrixTranslate(mV1, mV2); } + + /** + * Writes out the DrawOval to the buffer + * + * @param buffer buffer to write to + * @param x1 start x of DrawOval + * @param y1 start y of the DrawOval + */ + public static void apply(WireBuffer buffer, + float x1, + float y1) { + write(buffer, OP_CODE, x1, y1); + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/NamedVariable.java b/core/java/com/android/internal/widget/remotecompose/core/operations/NamedVariable.java index ae27f5ff450b..2cf83cd6caec 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/NamedVariable.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/NamedVariable.java @@ -15,11 +15,14 @@ */ package com.android.internal.widget.remotecompose.core.operations; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.UTF8; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import java.util.List; @@ -27,14 +30,16 @@ import java.util.List; * Operation to deal with Text data */ public class NamedVariable implements Operation { + private static final int OP_CODE = Operations.NAMED_VARIABLE; + private static final String CLASS_NAME = "NamedVariable"; public int mVarId; public String mVarName; public int mVarType; - public static final Companion COMPANION = new Companion(); public static final int MAX_STRING_SIZE = 4000; public static final int COLOR_TYPE = 2; public static final int FLOAT_TYPE = 1; public static final int STRING_TYPE = 0; + public NamedVariable(int varId, int varType, String name) { this.mVarId = varId; this.mVarType = varType; @@ -43,7 +48,7 @@ public class NamedVariable implements Operation { @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mVarId, mVarType, mVarName); + apply(buffer, mVarId, mVarType, mVarName); } @Override @@ -52,41 +57,44 @@ public class NamedVariable implements Operation { + Utils.trimString(mVarName, 10) + "\" type=" + mVarType; } - public static class Companion implements CompanionOperation { - private Companion() { - } + public static String name() { + return CLASS_NAME; + } - @Override - public String name() { - return "TextData"; - } + public static int id() { + return OP_CODE; + } - @Override - public int id() { - return Operations.DATA_TEXT; - } + /** + * Writes out the operation to the buffer + * + * @param buffer The buffer to write into + * @param varId id to label + * @param varType The type of variable + * @param text String + */ + public static void apply(WireBuffer buffer, int varId, int varType, String text) { + buffer.start(Operations.NAMED_VARIABLE); + buffer.writeInt(varId); + buffer.writeInt(varType); + buffer.writeUTF8(text); + } - /** - * Writes out the operation to the buffer - * @param buffer - * @param varId - * @param varType - * @param text - */ - public void apply(WireBuffer buffer, int varId, int varType, String text) { - buffer.start(Operations.NAMED_VARIABLE); - buffer.writeInt(varId); - buffer.writeInt(varType); - buffer.writeUTF8(text); - } + public static void read(WireBuffer buffer, List<Operation> operations) { + int varId = buffer.readInt(); + int varType = buffer.readInt(); + String text = buffer.readUTF8(MAX_STRING_SIZE); + operations.add(new NamedVariable(varId, varType, text)); + } - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int varId = buffer.readInt(); - int varType = buffer.readInt(); - String text = buffer.readUTF8(MAX_STRING_SIZE); - operations.add(new NamedVariable(varId, varType, text)); - } + public static void documentation(DocumentationBuilder doc) { + doc.operation("Data Operations", + OP_CODE, + CLASS_NAME) + .description("Add a string name for an ID") + .field(INT, "varId", "id to label") + .field(INT, "varType", "The type of variable") + .field(UTF8, "name", "String"); } @Override diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/PaintData.java b/core/java/com/android/internal/widget/remotecompose/core/operations/PaintData.java index 0807bcdcfebb..ae7a89279320 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/PaintData.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/PaintData.java @@ -15,7 +15,9 @@ */ package com.android.internal.widget.remotecompose.core.operations; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT_ARRAY; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; @@ -23,13 +25,15 @@ import com.android.internal.widget.remotecompose.core.PaintOperation; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.VariableSupport; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import com.android.internal.widget.remotecompose.core.operations.paint.PaintBundle; import java.util.List; public class PaintData extends PaintOperation implements VariableSupport { + private static final int OP_CODE = Operations.PAINT_VALUES; + private static final String CLASS_NAME = "PaintData"; public PaintBundle mPaintData = new PaintBundle(); - public static final Companion COMPANION = new Companion(); public static final int MAX_STRING_SIZE = 4000; public PaintData() { @@ -47,7 +51,7 @@ public class PaintData extends PaintOperation implements VariableSupport { @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mPaintData); + apply(buffer, mPaintData); } @Override @@ -55,31 +59,34 @@ public class PaintData extends PaintOperation implements VariableSupport { return "PaintData " + "\"" + mPaintData + "\""; } - public static class Companion implements CompanionOperation { - private Companion() { - } - - @Override - public String name() { - return "TextData"; - } - - @Override - public int id() { - return Operations.PAINT_VALUES; - } - - public void apply(WireBuffer buffer, PaintBundle paintBundle) { - buffer.start(Operations.PAINT_VALUES); - paintBundle.writeBundle(buffer); - } - - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - PaintData data = new PaintData(); - data.mPaintData.readBundle(buffer); - operations.add(data); - } + + public static String name() { + return CLASS_NAME; + } + + public static int id() { + return OP_CODE; + } + + public static void apply(WireBuffer buffer, PaintBundle paintBundle) { + buffer.start(Operations.PAINT_VALUES); + paintBundle.writeBundle(buffer); + } + + public static void read(WireBuffer buffer, List<Operation> operations) { + PaintData data = new PaintData(); + data.mPaintData.readBundle(buffer); + operations.add(data); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Data Operations", + OP_CODE, + CLASS_NAME) + .description("Encode a Paint ") + .field(INT, "length", "id string") + .field(INT_ARRAY, "paint", "length", + "path encoded as floats"); } @Override @@ -91,5 +98,4 @@ public class PaintData extends PaintOperation implements VariableSupport { public void paint(PaintContext context) { context.applyPaint(mPaintData); } - } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/PathData.java b/core/java/com/android/internal/widget/remotecompose/core/operations/PathData.java index e467e7b7f31e..91352d914a99 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/PathData.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/PathData.java @@ -15,18 +15,22 @@ */ package com.android.internal.widget.remotecompose.core.operations; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT_ARRAY; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.VariableSupport; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import java.util.Arrays; import java.util.List; public class PathData implements Operation, VariableSupport { - public static final Companion COMPANION = new Companion(); + private static final int OP_CODE = Operations.DATA_PATH; + private static final String CLASS_NAME = "PathData"; int mInstanceId; float[] mFloatPath; float[] mOutputPath; @@ -52,16 +56,16 @@ public class PathData implements Operation, VariableSupport { @Override public void registerListening(RemoteContext context) { - for (int i = 0; i < mFloatPath.length; i++) { - if (Float.isNaN(mFloatPath[i])) { - context.listensTo(Utils.idFromNan(mFloatPath[i]), this); + for (float v : mFloatPath) { + if (Float.isNaN(v)) { + context.listensTo(Utils.idFromNan(v), this); } } } @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mInstanceId, mOutputPath); + apply(buffer, mInstanceId, mOutputPath); } @Override @@ -113,42 +117,45 @@ public class PathData implements Operation, VariableSupport { public static final float CLOSE_NAN = Utils.asNan(CLOSE); public static final float DONE_NAN = Utils.asNan(DONE); - public static class Companion implements CompanionOperation { - - private Companion() { - } + public static String name() { + return CLASS_NAME; + } - @Override - public String name() { - return "BitmapData"; - } + public static int id() { + return OP_CODE; + } - @Override - public int id() { - return Operations.DATA_PATH; + public static void apply(WireBuffer buffer, int id, float[] data) { + buffer.start(Operations.DATA_PATH); + buffer.writeInt(id); + buffer.writeInt(data.length); + for (float datum : data) { + buffer.writeFloat(datum); } + } - public void apply(WireBuffer buffer, int id, float[] data) { - buffer.start(Operations.DATA_PATH); - buffer.writeInt(id); - buffer.writeInt(data.length); - for (int i = 0; i < data.length; i++) { - buffer.writeFloat(data[i]); - } + public static void read(WireBuffer buffer, List<Operation> operations) { + int imageId = buffer.readInt(); + int len = buffer.readInt(); + float[] data = new float[len]; + for (int i = 0; i < data.length; i++) { + data[i] = buffer.readFloat(); } + operations.add(new PathData(imageId, data)); + } - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int imageId = buffer.readInt(); - int len = buffer.readInt(); - float[] data = new float[len]; - for (int i = 0; i < data.length; i++) { - data[i] = buffer.readFloat(); - } - operations.add(new PathData(imageId, data)); - } + public static void documentation(DocumentationBuilder doc) { + doc.operation("Data Operations", + OP_CODE, + CLASS_NAME) + .description("Encode a Path ") + .field(INT, "id", "id string") + .field(INT, "length", "id string") + .field(FLOAT_ARRAY, "pathData", "length", + "path encoded as floats"); } + public static String pathString(float[] path) { if (path == null) { return "null"; diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentBehavior.java b/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentBehavior.java index 997e8dc791ed..33f997fc7266 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentBehavior.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentBehavior.java @@ -15,14 +15,14 @@ */ package com.android.internal.widget.remotecompose.core.operations; -import android.util.Log; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; -import com.android.internal.widget.remotecompose.core.CompanionOperation; import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.RemoteComposeOperation; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import java.util.List; @@ -33,7 +33,8 @@ import java.util.List; * as the dimensions of the document in pixels. */ public class RootContentBehavior implements RemoteComposeOperation { - + private static final int OP_CODE = Operations.ROOT_CONTENT_BEHAVIOR; + private static final String CLASS_NAME = "RootContentBehavior"; int mScroll = NONE; int mSizing = NONE; @@ -94,8 +95,6 @@ public class RootContentBehavior implements RemoteComposeOperation { public static final int SCALE_CROP = 5; public static final int SCALE_FILL_BOUNDS = 6; - public static final Companion COMPANION = new Companion(); - /** * Sets the way the player handles the content * @@ -123,7 +122,7 @@ public class RootContentBehavior implements RemoteComposeOperation { mScroll = scroll; break; default: { - Log.e(TAG, "incorrect scroll value " + scroll); + System.out.println(TAG + "incorrect scroll value " + scroll); } } if (alignment == ALIGNMENT_CENTER) { @@ -140,14 +139,14 @@ public class RootContentBehavior implements RemoteComposeOperation { if (validHorizontalAlignment && validVerticalAlignment) { mAlignment = alignment; } else { - Log.e(TAG, "incorrect alignment " + System.out.println(TAG + "incorrect alignment " + " h: " + horizontalContentAlignment + " v: " + verticalContentAlignment); } } switch (sizing) { case SIZING_LAYOUT: { - Log.e(TAG, "sizing_layout is not yet supported"); + System.out.println(TAG + "sizing_layout is not yet supported"); } break; case SIZING_SCALE: { @@ -155,12 +154,12 @@ public class RootContentBehavior implements RemoteComposeOperation { } break; default: { - Log.e(TAG, "incorrect sizing value " + sizing); + System.out.println(TAG + "incorrect sizing value " + sizing); } } if (mSizing == SIZING_LAYOUT) { if (mode != NONE) { - Log.e(TAG, "mode for sizing layout is not yet supported"); + System.out.println(TAG + "mode for sizing layout is not yet supported"); } } else if (mSizing == SIZING_SCALE) { switch (mode) { @@ -173,7 +172,7 @@ public class RootContentBehavior implements RemoteComposeOperation { mMode = mode; break; default: { - Log.e(TAG, "incorrect mode for scale sizing, mode: " + mode); + System.out.println(TAG + "incorrect mode for scale sizing, mode: " + mode); } } } @@ -181,7 +180,7 @@ public class RootContentBehavior implements RemoteComposeOperation { @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mScroll, mAlignment, mSizing, mMode); + apply(buffer, mScroll, mAlignment, mSizing, mMode); } @Override @@ -200,37 +199,67 @@ public class RootContentBehavior implements RemoteComposeOperation { return toString(); } - public static class Companion implements CompanionOperation { - private Companion() { - } - @Override - public String name() { - return "RootContentBehavior"; - } + public static String name() { + return CLASS_NAME; + } - @Override - public int id() { - return Operations.ROOT_CONTENT_BEHAVIOR; - } - public void apply(WireBuffer buffer, int scroll, int alignment, int sizing, int mode) { - buffer.start(Operations.ROOT_CONTENT_BEHAVIOR); - buffer.writeInt(scroll); - buffer.writeInt(alignment); - buffer.writeInt(sizing); - buffer.writeInt(mode); - } + public static int id() { + return OP_CODE; + } + + public static void apply(WireBuffer buffer, int scroll, int alignment, int sizing, int mode) { + buffer.start(OP_CODE); + buffer.writeInt(scroll); + buffer.writeInt(alignment); + buffer.writeInt(sizing); + buffer.writeInt(mode); + } + + + public static void read(WireBuffer buffer, List<Operation> operations) { + int scroll = buffer.readInt(); + int alignment = buffer.readInt(); + int sizing = buffer.readInt(); + int mode = buffer.readInt(); + RootContentBehavior rootContentBehavior = + new RootContentBehavior(scroll, alignment, sizing, mode); + operations.add(rootContentBehavior); + } + + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Protocol Operations", + OP_CODE, + CLASS_NAME) + .description("Describes the behaviour of the root") + .field(INT, "scroll", "scroll") + .possibleValues("SCROLL_HORIZONTAL", SCROLL_HORIZONTAL) + .possibleValues("SCROLL_VERTICAL", SCROLL_VERTICAL) + .field(INT, "alignment", "alignment") + .possibleValues("ALIGNMENT_TOP", ALIGNMENT_TOP) + .possibleValues("ALIGNMENT_VERTICAL_CENTER", ALIGNMENT_VERTICAL_CENTER) + .possibleValues("ALIGNMENT_BOTTOM", ALIGNMENT_BOTTOM) + .possibleValues("ALIGNMENT_START", ALIGNMENT_START) + .possibleValues("ALIGNMENT_START", ALIGNMENT_START) + .possibleValues("ALIGNMENT_END", ALIGNMENT_END) + .field(INT, "sizing", "sizing") + .possibleValues("SCALE_INSIDE", SCALE_INSIDE) + .possibleValues("SCALE_FIT", SCALE_FIT) + .possibleValues("SCALE_FILL_WIDTH", SCALE_FILL_WIDTH) + .possibleValues("SCALE_FILL_HEIGHT", SCALE_FILL_HEIGHT) + .possibleValues("SCALE_CROP", SCALE_CROP) + .possibleValues("SCALE_FILL_BOUNDS", SCALE_FILL_BOUNDS) + .field(INT, "mode", "mode") + .possibleValues("LAYOUT_HORIZONTAL_MATCH_PARENT", LAYOUT_HORIZONTAL_MATCH_PARENT) + .possibleValues("LAYOUT_HORIZONTAL_WRAP_CONTENT", LAYOUT_HORIZONTAL_WRAP_CONTENT) + .possibleValues("LAYOUT_HORIZONTAL_FIXED", LAYOUT_HORIZONTAL_FIXED) + .possibleValues("LAYOUT_VERTICAL_MATCH_PARENT", LAYOUT_VERTICAL_MATCH_PARENT) + .possibleValues("LAYOUT_VERTICAL_WRAP_CONTENT", LAYOUT_VERTICAL_WRAP_CONTENT) + .possibleValues("LAYOUT_VERTICAL_FIXED", LAYOUT_VERTICAL_FIXED) + .possibleValues("LAYOUT_MATCH_PARENT", LAYOUT_MATCH_PARENT) + .possibleValues("LAYOUT_WRAP_CONTENT", LAYOUT_WRAP_CONTENT); - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int scroll = buffer.readInt(); - int alignment = buffer.readInt(); - int sizing = buffer.readInt(); - int mode = buffer.readInt(); - RootContentBehavior rootContentBehavior = - new RootContentBehavior(scroll, alignment, sizing, mode); - operations.add(rootContentBehavior); - } } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentDescription.java b/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentDescription.java index 076b28edf981..e1533eefae53 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentDescription.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentDescription.java @@ -15,12 +15,14 @@ */ package com.android.internal.widget.remotecompose.core.operations; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.RemoteComposeOperation; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import java.util.List; @@ -28,10 +30,10 @@ import java.util.List; * Describe a content description for the document */ public class RootContentDescription implements RemoteComposeOperation { + private static final int OP_CODE = Operations.ROOT_CONTENT_DESCRIPTION; + private static final String CLASS_NAME = "RootContentDescription"; int mContentDescription; - public static final Companion COMPANION = new Companion(); - /** * Encodes a content description for the document * @@ -43,7 +45,7 @@ public class RootContentDescription implements RemoteComposeOperation { @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mContentDescription); + apply(buffer, mContentDescription); } @Override @@ -61,29 +63,32 @@ public class RootContentDescription implements RemoteComposeOperation { return toString(); } - public static class Companion implements CompanionOperation { - private Companion() {} - - @Override - public String name() { - return "RootContentDescription"; - } - - @Override - public int id() { - return Operations.ROOT_CONTENT_DESCRIPTION; - } - - public void apply(WireBuffer buffer, int contentDescription) { - buffer.start(Operations.ROOT_CONTENT_DESCRIPTION); - buffer.writeInt(contentDescription); - } - - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int contentDescription = buffer.readInt(); - RootContentDescription header = new RootContentDescription(contentDescription); - operations.add(header); - } + public static String name() { + return CLASS_NAME; + } + + public static int id() { + return OP_CODE; + } + + public static void apply(WireBuffer buffer, int contentDescription) { + buffer.start(Operations.ROOT_CONTENT_DESCRIPTION); + buffer.writeInt(contentDescription); + } + + public static void read(WireBuffer buffer, List<Operation> operations) { + int contentDescription = buffer.readInt(); + RootContentDescription header = new RootContentDescription(contentDescription); + operations.add(header); + } + + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Protocol Operations", + OP_CODE, + CLASS_NAME) + .description("Content description of root") + .field(INT, "id", "id of Int"); + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ShaderData.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ShaderData.java index 8463ac576774..c4dde6e0d358 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/ShaderData.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ShaderData.java @@ -15,12 +15,19 @@ */ package com.android.internal.widget.remotecompose.core.operations; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.BYTE; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT_ARRAY; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT_ARRAY; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.SHORT; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.UTF8; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.VariableSupport; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import java.util.Arrays; import java.util.HashMap; @@ -32,6 +39,8 @@ import java.util.List; * in playback the image is decompressed */ public class ShaderData implements Operation, VariableSupport { + private static final int OP_CODE = Operations.DATA_SHADER; + private static final String CLASS_NAME = "ShaderData"; int mShaderTextId; // the actual text of a shader int mShaderID; // allows shaders to be referenced by number HashMap<String, float[]> mUniformRawFloatMap = null; @@ -39,10 +48,6 @@ public class ShaderData implements Operation, VariableSupport { HashMap<String, int[]> mUniformIntMap = null; HashMap<String, Integer> mUniformBitmapMap = null; - public static final int MAX_IMAGE_DIMENSION = 8000; - - public static final Companion COMPANION = new Companion(); - public ShaderData(int shaderID, int shaderTextId, HashMap<String, float[]> floatMap, @@ -81,7 +86,8 @@ public class ShaderData implements Operation, VariableSupport { /** * get names of all known floats - * @return + * + * @return Names of all uniform floats or empty array */ public String[] getUniformFloatNames() { if (mUniformFloatMap == null) return new String[0]; @@ -90,8 +96,9 @@ public class ShaderData implements Operation, VariableSupport { /** * Get float values associated with the name - * @param name - * @return + * + * @param name name of uniform + * @return value of uniform */ public float[] getUniformFloats(String name) { return mUniformFloatMap.get(name); @@ -99,7 +106,8 @@ public class ShaderData implements Operation, VariableSupport { /** * get the name of all know uniform integers - * @return + * + * @return Name of all integer uniforms */ public String[] getUniformIntegerNames() { if (mUniformIntMap == null) return new String[0]; @@ -108,8 +116,9 @@ public class ShaderData implements Operation, VariableSupport { /** * Get Int value associated with the name - * @param name - * @return + * + * @param name Name of uniform + * @return value of uniform */ public int[] getUniformInts(String name) { return mUniformIntMap.get(name); @@ -117,7 +126,8 @@ public class ShaderData implements Operation, VariableSupport { /** * get list of uniform Bitmaps - * @return + * + * @return Name of all bitmap uniforms */ public String[] getUniformBitmapNames() { if (mUniformBitmapMap == null) return new String[0]; @@ -126,8 +136,9 @@ public class ShaderData implements Operation, VariableSupport { /** * Get a bitmap stored under that name - * @param name - * @return + * + * @param name Name of bitmap uniform + * @return Bitmap ID */ public int getUniformBitmapId(String name) { return mUniformBitmapMap.get(name); @@ -135,7 +146,7 @@ public class ShaderData implements Operation, VariableSupport { @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mShaderID, mShaderTextId, + apply(buffer, mShaderID, mShaderTextId, mUniformFloatMap, mUniformIntMap, mUniformBitmapMap); } @@ -165,136 +176,150 @@ public class ShaderData implements Operation, VariableSupport { public void registerListening(RemoteContext context) { for (String name : mUniformRawFloatMap.keySet()) { float[] value = mUniformRawFloatMap.get(name); - for (int i = 0; i < value.length; i++) { - if (Float.isNaN(value[i])) { - context.listensTo(Utils.idFromNan(value[i]), this); + for (float v : value) { + if (Float.isNaN(v)) { + context.listensTo(Utils.idFromNan(v), this); } } } } - public static class Companion implements CompanionOperation { - private Companion() { - } + public static String name() { + return CLASS_NAME; + } - @Override - public String name() { - return "BitmapData"; - } + public static int id() { + return OP_CODE; + } - @Override - public int id() { - return Operations.DATA_SHADER; - } + /** + * Writes out the operation to the buffer + * + * @param buffer buffer to write into + * @param shaderID id of shader + * @param shaderTextId id of text of shader + * @param floatMap the map of float uniforms + * @param intMap the map of int uniforms + * @param bitmapMap the map of bitmap uniforms + */ + public static void apply(WireBuffer buffer, int shaderID, int shaderTextId, + HashMap<String, float[]> floatMap, + HashMap<String, int[]> intMap, + HashMap<String, Integer> bitmapMap) { + buffer.start(OP_CODE); + buffer.writeInt(shaderID); + + buffer.writeInt(shaderTextId); + int floatSize = (floatMap == null) ? 0 : floatMap.size(); + int intSize = (intMap == null) ? 0 : intMap.size(); + int bitmapSize = (bitmapMap == null) ? 0 : bitmapMap.size(); + int sizes = floatSize | (intSize << 8) | (bitmapSize << 16); + buffer.writeInt(sizes); + + if (floatSize > 0) { - /** - * Writes out the operation to the buffer - * @param buffer - * @param shaderID - * @param shaderTextId - * @param floatMap - * @param intMap - * @param bitmapMap - */ - public void apply(WireBuffer buffer, int shaderID, int shaderTextId, - HashMap<String, float[]> floatMap, - HashMap<String, int[]> intMap, - HashMap<String, Integer> bitmapMap) { - buffer.start(Operations.DATA_SHADER); - buffer.writeInt(shaderID); - - buffer.writeInt(shaderTextId); - int floatSize = (floatMap == null) ? 0 : floatMap.size(); - int intSize = (intMap == null) ? 0 : intMap.size(); - int bitmapSize = (bitmapMap == null) ? 0 : bitmapMap.size(); - int sizes = floatSize | (intSize << 8) | (bitmapSize << 16); - buffer.writeInt(sizes); - - if (floatSize > 0) { - - for (String name : floatMap.keySet()) { - buffer.writeUTF8(name); - float[] values = floatMap.get(name); - buffer.writeInt(values.length); - - for (int i = 0; i < values.length; i++) { - buffer.writeFloat(values[i]); - } - } - } + for (String name : floatMap.keySet()) { + buffer.writeUTF8(name); + float[] values = floatMap.get(name); + buffer.writeInt(values.length); - if (intSize > 0) { - for (String name : intMap.keySet()) { - buffer.writeUTF8(name); - int[] values = intMap.get(name); - buffer.writeInt(values.length); - for (int i = 0; i < values.length; i++) { - buffer.writeInt(values[i]); - } + for (float value : values) { + buffer.writeFloat(value); } } - if (bitmapSize > 0) { - for (String name : bitmapMap.keySet()) { - buffer.writeUTF8(name); - int value = bitmapMap.get(name); + } + + if (intSize > 0) { + for (String name : intMap.keySet()) { + buffer.writeUTF8(name); + int[] values = intMap.get(name); + buffer.writeInt(values.length); + for (int value : values) { buffer.writeInt(value); } } } + if (bitmapSize > 0) { + for (String name : bitmapMap.keySet()) { + buffer.writeUTF8(name); + int value = bitmapMap.get(name); + buffer.writeInt(value); + } + } + } - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int shaderID = buffer.readInt(); - int shaderTextId = buffer.readInt(); - HashMap<String, float[]> floatMap = null; - HashMap<String, int[]> intMap = null; - HashMap<String, Integer> bitmapMap = null; - - int sizes = buffer.readInt(); - - int floatMapSize = sizes & 0xFF; - if (floatMapSize > 0) { - floatMap = new HashMap<>(); - for (int i = 0; i < floatMapSize; i++) { - String name = buffer.readUTF8(); - int len = buffer.readInt(); - float[] val = new float[len]; - - for (int j = 0; j < len; j++) { - val[j] = buffer.readFloat(); - } - floatMap.put(name, val); + public static void read(WireBuffer buffer, List<Operation> operations) { + int shaderID = buffer.readInt(); + int shaderTextId = buffer.readInt(); + HashMap<String, float[]> floatMap = null; + HashMap<String, int[]> intMap = null; + HashMap<String, Integer> bitmapMap = null; + + int sizes = buffer.readInt(); + + int floatMapSize = sizes & 0xFF; + if (floatMapSize > 0) { + floatMap = new HashMap<>(); + for (int i = 0; i < floatMapSize; i++) { + String name = buffer.readUTF8(); + int len = buffer.readInt(); + float[] val = new float[len]; + + for (int j = 0; j < len; j++) { + val[j] = buffer.readFloat(); } + + floatMap.put(name, val); } - int intMapSize = (sizes >> 8) & 0xFF; + } + int intMapSize = (sizes >> 8) & 0xFF; - if (intMapSize > 0) { + if (intMapSize > 0) { - intMap = new HashMap<>(); - for (int i = 0; i < intMapSize; i++) { - String name = buffer.readUTF8(); - int len = buffer.readInt(); - int[] val = new int[len]; - for (int j = 0; j < len; j++) { - val[j] = buffer.readInt(); - } - intMap.put(name, val); + intMap = new HashMap<>(); + for (int i = 0; i < intMapSize; i++) { + String name = buffer.readUTF8(); + int len = buffer.readInt(); + int[] val = new int[len]; + for (int j = 0; j < len; j++) { + val[j] = buffer.readInt(); } + intMap.put(name, val); } - int bitmapMapSize = (sizes >> 16) & 0xFF; - - if (bitmapMapSize > 0) { - bitmapMap = new HashMap<>(); - for (int i = 0; i < bitmapMapSize; i++) { - String name = buffer.readUTF8(); - int val = buffer.readInt(); - bitmapMap.put(name, val); - } + } + int bitmapMapSize = (sizes >> 16) & 0xFF; + + if (bitmapMapSize > 0) { + bitmapMap = new HashMap<>(); + for (int i = 0; i < bitmapMapSize; i++) { + String name = buffer.readUTF8(); + int val = buffer.readInt(); + bitmapMap.put(name, val); } - operations.add(new ShaderData(shaderID, shaderTextId, - floatMap, intMap, bitmapMap)); } + operations.add(new ShaderData(shaderID, shaderTextId, + floatMap, intMap, bitmapMap)); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Data Operations", + OP_CODE, + CLASS_NAME) + .description("Shader") + .field(INT, "shaderID", "id of shader") + .field(BYTE, " floatSize", "number of float uniforms") + .field(BYTE, " intSize", "number of int uniform") + .field(SHORT, " intSize", "number of int uniform") + .field(UTF8, "floatName", "name of float uniform") + .field(INT, "length", "length") + .field(FLOAT_ARRAY, "VALUE", "float uniform (max 4)") + .field(UTF8, "IntName", "id of shader text") + .field(INT, "length", "length of uniform") + .field(INT_ARRAY, "VALUE", "int uniform (max 4)") + .field(UTF8, "bitmapName", "name of bitmap") + .field(INT, "VALUE", "id of bitmap"); + } @Override diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/TextData.java b/core/java/com/android/internal/widget/remotecompose/core/operations/TextData.java index ed1344975256..b49cb7664495 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/TextData.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/TextData.java @@ -15,21 +15,27 @@ */ package com.android.internal.widget.remotecompose.core.operations; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.UTF8; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.RemoteContext; +import com.android.internal.widget.remotecompose.core.SerializableToString; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; +import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer; import java.util.List; /** * Operation to deal with Text data */ -public class TextData implements Operation { +public class TextData implements Operation, SerializableToString { + private static final int OP_CODE = Operations.DATA_TEXT; + private static final String CLASS_NAME = "TextData"; public int mTextId; public String mText; - public static final Companion COMPANION = new Companion(); public static final int MAX_STRING_SIZE = 4000; public TextData(int textId, String text) { @@ -39,7 +45,7 @@ public class TextData implements Operation { @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mTextId, mText); + apply(buffer, mTextId, mText); } @Override @@ -48,35 +54,41 @@ public class TextData implements Operation { + Utils.trimString(mText, 10) + "\""; } - public static class Companion implements CompanionOperation { - private Companion() { - } - - @Override - public String name() { - return "TextData"; - } - - @Override - public int id() { - return Operations.DATA_TEXT; - } - - public void apply(WireBuffer buffer, int textId, String text) { - buffer.start(Operations.DATA_TEXT); - buffer.writeInt(textId); - buffer.writeUTF8(text); - } - - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int textId = buffer.readInt(); - - String text = buffer.readUTF8(MAX_STRING_SIZE); - operations.add(new TextData(textId, text)); - } + public static String name() { + return CLASS_NAME; + } + + + public static int id() { + return OP_CODE; + } + + public static void apply(WireBuffer buffer, int textId, String text) { + buffer.start(OP_CODE); + buffer.writeInt(textId); + buffer.writeUTF8(text); + } + + + public static void read(WireBuffer buffer, List<Operation> operations) { + int textId = buffer.readInt(); + + String text = buffer.readUTF8(MAX_STRING_SIZE); + operations.add(new TextData(textId, text)); } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Data Operations", + OP_CODE, + CLASS_NAME) + .description("Encode a string ") + .field(INT, "id", "id string") + .field(UTF8, "text", + "encode text as a string"); + } + + @Override public void apply(RemoteContext context) { context.loadText(mTextId, mText); @@ -86,4 +98,14 @@ public class TextData implements Operation { public String deepToString(String indent) { return indent + toString(); } + + @Override + public void serializeToString(int indent, StringSerializer serializer) { + serializer.append(indent, getSerializedName() + "<" + mTextId + + "> = \"" + mText + "\""); + } + + private String getSerializedName() { + return "DATA_TEXT"; + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/TextFromFloat.java b/core/java/com/android/internal/widget/remotecompose/core/operations/TextFromFloat.java index 65a39a1eba04..8f235dcca28c 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/TextFromFloat.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/TextFromFloat.java @@ -15,12 +15,15 @@ */ package com.android.internal.widget.remotecompose.core.operations; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.SHORT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.VariableSupport; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import com.android.internal.widget.remotecompose.core.operations.utilities.StringUtils; import java.util.List; @@ -31,13 +34,14 @@ import java.util.List; * before and after define number of digits before and after the decimal point */ public class TextFromFloat implements Operation, VariableSupport { + private static final int OP_CODE = Operations.TEXT_FROM_FLOAT; + private static final String CLASS_NAME = "TextFromFloat"; public int mTextId; public float mValue; public float mOutValue; public short mDigitsBefore; public short mDigitsAfter; public int mFlags; - public static final Companion COMPANION = new Companion(); public static final int MAX_STRING_SIZE = 4000; char mPre = ' '; char mAfter = ' '; @@ -83,7 +87,7 @@ public class TextFromFloat implements Operation, VariableSupport { @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mTextId, mValue, mDigitsAfter, mDigitsBefore, mFlags); + apply(buffer, mTextId, mValue, mDigitsAfter, mDigitsBefore, mFlags); } @Override @@ -99,10 +103,8 @@ public class TextFromFloat implements Operation, VariableSupport { if (Float.isNaN(mValue)) { mOutValue = context.getFloat(Utils.idFromNan(mValue)); } - } - @Override public void registerListening(RemoteContext context) { if (Float.isNaN(mValue)) { @@ -110,53 +112,63 @@ public class TextFromFloat implements Operation, VariableSupport { } } - public static class Companion implements CompanionOperation { - private Companion() { - } + public static String name() { + return CLASS_NAME; + } - @Override - public String name() { - return "TextData"; - } + public static int id() { + return OP_CODE; + } - @Override - public int id() { - return Operations.TEXT_FROM_FLOAT; - } + /** + * Writes out the operation to the buffer + * + * @param buffer buffer to write to + * @param textId the id of the output text + * @param value the float value to be turned into strings + * @param digitsBefore the digits before the decimal point + * @param digitsAfter the digits after the decimal point + * @param flags flags that control if and how to fill the empty spots + */ + public static void apply(WireBuffer buffer, int textId, + float value, short digitsBefore, + short digitsAfter, int flags) { + buffer.start(OP_CODE); + buffer.writeInt(textId); + buffer.writeFloat(value); + buffer.writeInt((digitsBefore << 16) | digitsAfter); + buffer.writeInt(flags); - /** - * Writes out the operation to the buffer - * @param buffer - * @param textId - * @param value - * @param digitsBefore - * @param digitsAfter - * @param flags - */ - public void apply(WireBuffer buffer, int textId, - float value, short digitsBefore, - short digitsAfter, int flags) { - buffer.start(Operations.TEXT_FROM_FLOAT); - buffer.writeInt(textId); - buffer.writeFloat(value); - buffer.writeInt((digitsBefore << 16) | digitsAfter); - buffer.writeInt(flags); + } - } + public static void read(WireBuffer buffer, List<Operation> operations) { + int textId = buffer.readInt(); + float value = buffer.readFloat(); + int tmp = buffer.readInt(); + short post = (short) (tmp & 0xFFFF); + short pre = (short) ((tmp >> 16) & 0xFFFF); - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int textId = buffer.readInt(); - float value = buffer.readFloat(); - int tmp = buffer.readInt(); - short post = (short) (tmp & 0xFFFF); - short pre = (short) ((tmp >> 16) & 0xFFFF); + int flags = buffer.readInt(); + operations.add(new TextFromFloat(textId, value, pre, post, flags)); + } - int flags = buffer.readInt(); - operations.add(new TextFromFloat(textId, value, pre, post, flags)); - } + public static void documentation(DocumentationBuilder doc) { + doc.operation("Expressions Operations", + OP_CODE, + CLASS_NAME) + .description("Draw text along path object") + .field(INT, "textId", + "id of the text generated") + .field(INT, "value", + "Value to add") + .field(SHORT, "prePoint", + "digits before the decimal point") + .field(SHORT, "pstPoint", + "digit after the decimal point") + .field(INT, "flags", "options on padding"); } + @Override public void apply(RemoteContext context) { float v = mOutValue; diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/TextMerge.java b/core/java/com/android/internal/widget/remotecompose/core/operations/TextMerge.java index a0fc854f38f4..dd7822308a94 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/TextMerge.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/TextMerge.java @@ -15,11 +15,13 @@ */ package com.android.internal.widget.remotecompose.core.operations; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import java.util.List; @@ -27,11 +29,11 @@ import java.util.List; * Operation to deal with Text data */ public class TextMerge implements Operation { + private static final int OP_CODE = Operations.TEXT_MERGE; + private static final String CLASS_NAME = "TextMerge"; public int mTextId; public int mSrcId1; public int mSrcId2; - public static final Companion COMPANION = new Companion(); - public static final int MAX_STRING_SIZE = 4000; public TextMerge(int textId, int srcId1, int srcId2) { this.mTextId = textId; @@ -41,7 +43,7 @@ public class TextMerge implements Operation { @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mTextId, mSrcId1, mSrcId2); + apply(buffer, mTextId, mSrcId1, mSrcId2); } @Override @@ -49,42 +51,49 @@ public class TextMerge implements Operation { return "TextMerge[" + mTextId + "] = [" + mSrcId1 + " ] + [ " + mSrcId2 + "]"; } - public static class Companion implements CompanionOperation { - private Companion() { - } - - @Override - public String name() { - return "TextData"; - } - - @Override - public int id() { - return Operations.TEXT_MERGE; - } - - /** - * Writes out the operation to the buffer - * @param buffer - * @param textId - * @param srcId1 - * @param srcId2 - */ - public void apply(WireBuffer buffer, int textId, int srcId1, int srcId2) { - buffer.start(Operations.TEXT_MERGE); - buffer.writeInt(textId); - buffer.writeInt(srcId1); - buffer.writeInt(srcId2); - } - - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int textId = buffer.readInt(); - int srcId1 = buffer.readInt(); - int srcId2 = buffer.readInt(); - - operations.add(new TextMerge(textId, srcId1, srcId2)); - } + + public static String name() { + return CLASS_NAME; + } + + public static int id() { + return OP_CODE; + } + + /** + * Writes out the operation to the buffer + * + * @param buffer buffer to write to + * @param textId id of the text + * @param srcId1 source text 1 + * @param srcId2 source text 2 + */ + public static void apply(WireBuffer buffer, int textId, int srcId1, int srcId2) { + buffer.start(OP_CODE); + buffer.writeInt(textId); + buffer.writeInt(srcId1); + buffer.writeInt(srcId2); + } + + public static void read(WireBuffer buffer, List<Operation> operations) { + int textId = buffer.readInt(); + int srcId1 = buffer.readInt(); + int srcId2 = buffer.readInt(); + + operations.add(new TextMerge(textId, srcId1, srcId2)); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Data Operations", + OP_CODE, + CLASS_NAME) + .description("Merge two string into one") + .field(INT, "textId", + "id of the text") + .field(INT, "srcTextId1", + "id of the path") + .field(INT, "srcTextId1", + "x Shift of the text"); } @Override diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/Theme.java b/core/java/com/android/internal/widget/remotecompose/core/operations/Theme.java index f98299770570..52ae7fe5ab4b 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/Theme.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/Theme.java @@ -23,7 +23,6 @@ import com.android.internal.widget.remotecompose.core.RemoteComposeOperation; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.WireBuffer; import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; -import com.android.internal.widget.remotecompose.core.documentation.DocumentedCompanionOperation; import java.util.List; @@ -34,13 +33,13 @@ import java.util.List; * */ public class Theme implements RemoteComposeOperation { + private static final int OP_CODE = Operations.THEME; + private static final String CLASS_NAME = "Theme"; int mTheme; public static final int UNSPECIFIED = -1; public static final int DARK = -2; public static final int LIGHT = -3; - public static final Companion COMPANION = new Companion(); - /** * we can then filter operations depending on the chosen theme. * @@ -55,7 +54,7 @@ public class Theme implements RemoteComposeOperation { @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mTheme); + apply(buffer, mTheme); } @Override @@ -73,38 +72,32 @@ public class Theme implements RemoteComposeOperation { return indent + toString(); } - public static class Companion implements DocumentedCompanionOperation { - private Companion() {} - - @Override - public String name() { - return "Theme"; - } - - @Override - public int id() { - return Operations.THEME; - } - - public void apply(WireBuffer buffer, int theme) { - buffer.start(Operations.THEME); - buffer.writeInt(theme); - } - - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int theme = buffer.readInt(); - operations.add(new Theme(theme)); - } - - @Override - public void documentation(DocumentationBuilder doc) { - doc.operation("Protocol Operations", id(), name()) - .description("Set a theme") - .field(INT, "THEME", "theme id") - .possibleValues("UNSPECIFIED", Theme.UNSPECIFIED) - .possibleValues("DARK", Theme.DARK) - .possibleValues("LIGHT", Theme.LIGHT); - } + public static String name() { + return CLASS_NAME; + } + + + public static int id() { + return OP_CODE; + } + + public static void apply(WireBuffer buffer, int theme) { + buffer.start(OP_CODE); + buffer.writeInt(theme); + } + + + public static void read(WireBuffer buffer, List<Operation> operations) { + int theme = buffer.readInt(); + operations.add(new Theme(theme)); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Protocol Operations", OP_CODE, CLASS_NAME) + .description("Set a theme") + .field(INT, "THEME", "theme id") + .possibleValues("UNSPECIFIED", Theme.UNSPECIFIED) + .possibleValues("DARK", Theme.DARK) + .possibleValues("LIGHT", Theme.LIGHT); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/Utils.java b/core/java/com/android/internal/widget/remotecompose/core/operations/Utils.java index e9b0c3b11044..6e858c7e0215 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/Utils.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/Utils.java @@ -25,7 +25,12 @@ public class Utils { public static int idFromNan(float value) { int b = Float.floatToRawIntBits(value); - return b & 0xFFFFF; + return b & 0x3FFFFF; + } + + public static String idStringFromNan(float value) { + int b = Float.floatToRawIntBits(value) & 0x3FFFFF; + return (b > 0xFFFFF) ? "A_" + (b & 0xFFFFF) : "" + b; } public static float getActualValue(float lr) { diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ActionOperation.java new file mode 100644 index 000000000000..7588c794190d --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ActionOperation.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget.remotecompose.core.operations.layout; + +import com.android.internal.widget.remotecompose.core.CoreDocument; +import com.android.internal.widget.remotecompose.core.Operation; +import com.android.internal.widget.remotecompose.core.RemoteContext; +import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer; + +/** + * Operations representing actions on the document + */ +public interface ActionOperation extends Operation { + void serializeToString(int indent, StringSerializer serializer); + void runAction(RemoteContext context, CoreDocument document, + Component component, float x, float y); +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/CanvasContent.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/CanvasContent.java new file mode 100644 index 000000000000..fd3501732e51 --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/CanvasContent.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget.remotecompose.core.operations.layout; + +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; + +import com.android.internal.widget.remotecompose.core.Operation; +import com.android.internal.widget.remotecompose.core.Operations; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; + +import java.util.List; + +/** + * Represents the content of a CanvasLayout (i.e. contains the canvas commands) + */ +public class CanvasContent extends Component implements ComponentStartOperation { + + public CanvasContent(int componentId, float x, float y, + float width, float height, Component parent, int animationId) { + super(parent, componentId, animationId, x, y, width, height); + } + + public static String name() { + return "CanvasContent"; + } + + public static int id() { + return Operations.LAYOUT_CANVAS_CONTENT; + } + + @Override protected String getSerializedName() { + return "CANVAS_CONTENT"; + } + + public static void apply(WireBuffer buffer, int componentId) { + buffer.start(Operations.LAYOUT_CANVAS_CONTENT); + buffer.writeInt(componentId); + } + + public static void read(WireBuffer buffer, List<Operation> operations) { + int componentId = buffer.readInt(); + operations.add(new CanvasContent( + componentId, 0, 0, 0, 0, null, -1)); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Layout Operations", id(), name()) + .field(INT, "COMPONENT_ID", "unique id for this component") + .description("Container for canvas commands."); + } + + @Override + public void write(WireBuffer buffer) { + apply(buffer, mComponentId); + } +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ClickModifierEnd.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ClickModifierEnd.java new file mode 100644 index 000000000000..f7c6ce24df14 --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ClickModifierEnd.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget.remotecompose.core.operations.layout; + +import com.android.internal.widget.remotecompose.core.Operation; +import com.android.internal.widget.remotecompose.core.Operations; +import com.android.internal.widget.remotecompose.core.RemoteContext; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; + +import java.util.List; + +public class ClickModifierEnd implements Operation { + + @Override + public void write(WireBuffer buffer) { + apply(buffer); + } + + @Override + public String toString() { + return "CLICK_END"; + } + + @Override + public void apply(RemoteContext context) { + // nothing + } + + @Override + public String deepToString(String indent) { + return (indent != null ? indent : "") + toString(); + } + + public static String name() { + return "ClickModifierEnd"; + } + + public static int id() { + return Operations.MODIFIER_CLICK_END; + } + + public static void apply(WireBuffer buffer) { + buffer.start(id()); + } + + + public static void read(WireBuffer buffer, List<Operation> operations) { + operations.add(new ClickModifierEnd()); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Layout Operations", id(), name()) + .description("End tag for click modifiers. This operation marks the end" + + "of a click modifier"); + } +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ClickModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ClickModifierOperation.java new file mode 100644 index 000000000000..d75f70b674c5 --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ClickModifierOperation.java @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget.remotecompose.core.operations.layout; + +import com.android.internal.widget.remotecompose.core.CoreDocument; +import com.android.internal.widget.remotecompose.core.Operation; +import com.android.internal.widget.remotecompose.core.Operations; +import com.android.internal.widget.remotecompose.core.PaintContext; +import com.android.internal.widget.remotecompose.core.PaintOperation; +import com.android.internal.widget.remotecompose.core.RemoteContext; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; +import com.android.internal.widget.remotecompose.core.operations.TextData; +import com.android.internal.widget.remotecompose.core.operations.Utils; +import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ModifierOperation; +import com.android.internal.widget.remotecompose.core.operations.paint.PaintBundle; +import com.android.internal.widget.remotecompose.core.operations.utilities.ColorUtils; +import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer; +import com.android.internal.widget.remotecompose.core.operations.utilities.easing.Easing; +import com.android.internal.widget.remotecompose.core.operations.utilities.easing.FloatAnimation; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a click modifier + actions + */ +public class ClickModifierOperation extends PaintOperation + implements ModifierOperation, DecoratorComponent { + private static final int OP_CODE = Operations.MODIFIER_CLICK; + + + long mAnimateRippleStart = 0; + float mAnimateRippleX = 0f; + float mAnimateRippleY = 0f; + int mAnimateRippleDuration = 1000; + + float mWidth = 0; + float mHeight = 0; + + public float[] locationInWindow = new float[2]; + + PaintBundle mPaint = new PaintBundle(); + + public void animateRipple(float x, float y) { + mAnimateRippleStart = System.currentTimeMillis(); + mAnimateRippleX = x; + mAnimateRippleY = y; + } + public ArrayList<Operation> mList = new ArrayList<>(); + + public ArrayList<Operation> getList() { + return mList; + } + + @Override + public void write(WireBuffer buffer) { + apply(buffer); + } + + @Override + public String toString() { + return "ClickModifier"; + } + + @Override + public void apply(RemoteContext context) { + for (Operation op : mList) { + if (op instanceof TextData) { + op.apply(context); + } + } + } + + @Override + public String deepToString(String indent) { + return (indent != null ? indent : "") + toString(); + } + + @Override + public void paint(PaintContext context) { + if (mAnimateRippleStart == 0) { + return; + } + context.needsRepaint(); + + float progress = (System.currentTimeMillis() - mAnimateRippleStart); + progress /= (float) mAnimateRippleDuration; + if (progress > 1f) { + mAnimateRippleStart = 0; + } + progress = Math.min(1f, progress); + context.save(); + context.savePaint(); + mPaint.reset(); + + FloatAnimation anim1 = new FloatAnimation(Easing.CUBIC_STANDARD, 1f, + null, Float.NaN, Float.NaN); + anim1.setInitialValue(0f); + anim1.setTargetValue(1f); + float tween = anim1.get(progress); + + FloatAnimation anim2 = new FloatAnimation(Easing.CUBIC_STANDARD, 0.5f, + null, Float.NaN, Float.NaN); + anim2.setInitialValue(0f); + anim2.setTargetValue(1f); + float tweenRadius = anim2.get(progress); + + int startColor = ColorUtils.createColor(250, 250, 250, 180); + int endColor = ColorUtils.createColor(200, 200, 200, 0); + int paintedColor = Utils.interpolateColor(startColor, endColor, tween); + + float radius = Math.max(mWidth, mHeight) * tweenRadius; + mPaint.setColor(paintedColor); + context.applyPaint(mPaint); + context.clipRect(0f, 0f, mWidth, mHeight); + context.drawCircle(mAnimateRippleX, mAnimateRippleY, radius); + context.restorePaint(); + context.restore(); + } + + @Override + public void layout(RemoteContext context, float width, float height) { + mWidth = width; + mHeight = height; + } + + @Override + public void serializeToString(int indent, StringSerializer serializer) { + serializer.append(indent, "CLICK_MODIFIER"); + for (Operation o : mList) { + if (o instanceof ActionOperation) { + ((ActionOperation) o).serializeToString(indent + 1, serializer); + } + } + } + + @Override + public void onClick(RemoteContext context, CoreDocument document, + Component component, float x, float y) { + locationInWindow[0] = 0f; + locationInWindow[1] = 0f; + component.getLocationInWindow(locationInWindow); + animateRipple(x - locationInWindow[0], y - locationInWindow[1]); + for (Operation o : mList) { + if (o instanceof ActionOperation) { + ((ActionOperation) o).runAction(context, document, component, x, y); + } + } + } + + public static String name() { + return "ClickModifier"; + } + + public static void apply(WireBuffer buffer) { + buffer.start(OP_CODE); + } + + public static void read(WireBuffer buffer, List<Operation> operations) { + operations.add(new ClickModifierOperation()); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Layout Operations", OP_CODE, name()) + .description("Click modifier. This operation contains" + + " a list of action executed on click"); + } +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Component.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Component.java index ee2e11be6c1e..fca0b1344a10 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Component.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Component.java @@ -15,11 +15,17 @@ */ package com.android.internal.widget.remotecompose.core.operations.layout; +import com.android.internal.widget.remotecompose.core.CoreDocument; import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.PaintContext; import com.android.internal.widget.remotecompose.core.PaintOperation; import com.android.internal.widget.remotecompose.core.RemoteContext; +import com.android.internal.widget.remotecompose.core.SerializableToString; +import com.android.internal.widget.remotecompose.core.VariableSupport; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.operations.BitmapData; +import com.android.internal.widget.remotecompose.core.operations.ComponentValue; +import com.android.internal.widget.remotecompose.core.operations.TextData; import com.android.internal.widget.remotecompose.core.operations.layout.animation.AnimateMeasure; import com.android.internal.widget.remotecompose.core.operations.layout.animation.AnimationSpec; import com.android.internal.widget.remotecompose.core.operations.layout.measure.ComponentMeasure; @@ -30,11 +36,14 @@ import com.android.internal.widget.remotecompose.core.operations.paint.PaintBund import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer; import java.util.ArrayList; +import java.util.HashSet; /** * Generic Component class */ -public class Component extends PaintOperation implements Measurable { +public class Component extends PaintOperation implements Measurable, SerializableToString { + + private static final boolean DEBUG = false; protected int mComponentId = -1; protected float mX; @@ -44,6 +53,7 @@ public class Component extends PaintOperation implements Measurable { protected Component mParent; protected int mAnimationId = -1; public Visibility mVisibility = Visibility.VISIBLE; + public Visibility mScheduledVisibility = Visibility.VISIBLE; public ArrayList<Operation> mList = new ArrayList<>(); public PaintOperation mPreTranslate; public boolean mNeedsMeasure = true; @@ -52,22 +62,29 @@ public class Component extends PaintOperation implements Measurable { public AnimationSpec mAnimationSpec = new AnimationSpec(); public boolean mFirstLayout = true; PaintBundle mPaint = new PaintBundle(); + protected HashSet<ComponentValue> mComponentValues = new HashSet<>(); + public ArrayList<Operation> getList() { return mList; } + public float getX() { return mX; } + public float getY() { return mY; } + public float getWidth() { return mWidth; } + public float getHeight() { return mHeight; } + public int getComponentId() { return mComponentId; } @@ -79,19 +96,55 @@ public class Component extends PaintOperation implements Measurable { public Component getParent() { return mParent; } + public void setX(float value) { mX = value; } + public void setY(float value) { mY = value; } + public void setWidth(float value) { mWidth = value; } + public void setHeight(float value) { mHeight = value; } + /** + * Utility function to update variables referencing this component dimensions + * + * @param context the current context + */ + private void updateComponentValues(RemoteContext context) { + if (DEBUG) { + System.out.println("UPDATE COMPONENT VALUES (" + + mComponentValues.size() + + ") FOR " + mComponentId); + } + for (ComponentValue v : mComponentValues) { + switch (v.getType()) { + case ComponentValue.WIDTH: { + context.loadFloat(v.getValueId(), mWidth); + if (DEBUG) { + System.out.println("Updating WIDTH for " + mComponentId + " to " + mWidth); + } + } + break; + case ComponentValue.HEIGHT: { + context.loadFloat(v.getValueId(), mHeight); + if (DEBUG) { + System.out.println("Updating HEIGHT for " + mComponentId + + " to " + mHeight); + } + } + break; + } + } + } + public void setComponentId(int id) { mComponentId = id; } @@ -145,6 +198,30 @@ public class Component extends PaintOperation implements Measurable { mParent = parent; } + /** + * This traverses the component tree and make sure to + * update variables referencing the component dimensions as needed. + * + * @param context the current context + */ + public void updateVariables(RemoteContext context) { + if (!mComponentValues.isEmpty()) { + updateComponentValues(context); + } + for (Operation o : mList) { + if (o instanceof Component) { + ((Component) o).updateVariables(context); + } + if (o instanceof VariableSupport) { + o.apply(context); + } + } + } + + public void addComponentValue(ComponentValue v) { + mComponentValues.add(v); + } + public enum Visibility { VISIBLE, INVISIBLE, @@ -161,6 +238,13 @@ public class Component extends PaintOperation implements Measurable { return true; } + public void setVisibility(Visibility visibility) { + if (visibility != mVisibility) { + mScheduledVisibility = visibility; + invalidateMeasure(); + } + } + @Override public void measure(PaintContext context, float minWidth, float maxWidth, float minHeight, float maxHeight, MeasurePass measure) { @@ -172,7 +256,8 @@ public class Component extends PaintOperation implements Measurable { @Override public void layout(RemoteContext context, MeasurePass measure) { ComponentMeasure m = measure.get(this); - if (!mFirstLayout && context.isAnimationEnabled()) { + if (!mFirstLayout && context.isAnimationEnabled() + && !(this instanceof LayoutComponentContent)) { if (mAnimateMeasure == null) { ComponentMeasure origin = new ComponentMeasure(mComponentId, mX, mY, mWidth, mHeight, mVisibility); @@ -190,8 +275,8 @@ public class Component extends PaintOperation implements Measurable { } else { mVisibility = m.getVisibility(); } - mWidth = m.getW(); - mHeight = m.getH(); + setWidth(m.getW()); + setHeight(m.getH()); setLayoutPosition(m.getX(), m.getY()); mFirstLayout = false; } @@ -209,16 +294,16 @@ public class Component extends PaintOperation implements Measurable { return x >= lx1 && x < lx2 && y >= ly1 && y < ly2; } - public void onClick(float x, float y) { + public void onClick(RemoteContext context, CoreDocument document, float x, float y) { if (!contains(x, y)) { return; } for (Operation op : mList) { if (op instanceof Component) { - ((Component) op).onClick(x, y); + ((Component) op).onClick(context, document, x, y); } if (op instanceof ComponentModifiers) { - ((ComponentModifiers) op).onClick(x, y); + ((ComponentModifiers) op).onClick(context, document, this, x, y); } } } @@ -226,10 +311,11 @@ public class Component extends PaintOperation implements Measurable { public void getLocationInWindow(float[] value) { value[0] += mX; value[1] += mY; - if (mParent != null && mParent instanceof Component) { + if (mParent != null) { if (mParent instanceof LayoutComponent) { - value[0] += ((LayoutComponent) mParent).getMarginLeft(); - value[1] += ((LayoutComponent) mParent).getMarginTop(); + LayoutComponent parent = (LayoutComponent) mParent; + value[0] += parent.getMarginLeft() + parent.getPaddingLeft(); + value[1] += parent.getMarginTop() + parent.getPaddingTop(); } mParent.getLocationInWindow(value); } @@ -248,10 +334,10 @@ public class Component extends PaintOperation implements Measurable { public void serializeToString(int indent, StringSerializer serializer) { serializer.append(indent, getSerializedName() + " [" + mComponentId - + ":" + mAnimationId + "] = " - + "[" + mX + ", " + mY + ", " + mWidth + ", " + mHeight + "] " - + mVisibility - // + " [" + mNeedsMeasure + ", " + mNeedsRepaint + "]" + + ":" + mAnimationId + "] = " + + "[" + mX + ", " + mY + ", " + mWidth + ", " + mHeight + "] " + + mVisibility + // + " [" + mNeedsMeasure + ", " + mNeedsRepaint + "]" ); } @@ -382,6 +468,9 @@ public class Component extends PaintOperation implements Measurable { debugBox(this, context); } for (Operation op : mList) { + if (op instanceof BitmapData) { + ((BitmapData) op).apply(context.getContext()); + } if (op instanceof PaintOperation) { ((PaintOperation) op).paint(context); } @@ -435,6 +524,14 @@ public class Component extends PaintOperation implements Measurable { } } + public void getData(ArrayList<TextData> data) { + for (Operation op : mList) { + if (op instanceof TextData) { + data.add((TextData) op); + } + } + } + public int getComponentCount() { int count = 0; for (Operation op : mList) { diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentEnd.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentEnd.java index 8a523a20cab1..71decd74a40b 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentEnd.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentEnd.java @@ -20,17 +20,14 @@ import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.WireBuffer; import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; -import com.android.internal.widget.remotecompose.core.documentation.DocumentedCompanionOperation; import java.util.List; public class ComponentEnd implements Operation { - public static final ComponentEnd.Companion COMPANION = new ComponentEnd.Companion(); - @Override public void write(WireBuffer buffer) { - Companion.apply(buffer); + apply(buffer); } @Override @@ -48,35 +45,30 @@ public class ComponentEnd implements Operation { return (indent != null ? indent : "") + toString(); } - public static class Companion implements DocumentedCompanionOperation { - @Override - public String name() { - return "ComponentEnd"; - } + public static String name() { + return "ComponentEnd"; + } - @Override - public int id() { - return Operations.COMPONENT_END; - } + public static int id() { + return Operations.COMPONENT_END; + } - public static void apply(WireBuffer buffer) { - buffer.start(Operations.COMPONENT_END); - } + public static void apply(WireBuffer buffer) { + buffer.start(Operations.COMPONENT_END); + } + + public static int size() { + return 1 + 4 + 4 + 4; + } - public static int size() { - return 1 + 4 + 4 + 4; - } - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - operations.add(new ComponentEnd()); - } + public static void read(WireBuffer buffer, List<Operation> operations) { + operations.add(new ComponentEnd()); + } - @Override - public void documentation(DocumentationBuilder doc) { - doc.operation("Layout Operations", id(), name()) - .description("End tag for components / layouts. This operation marks the end" - + "of a component"); - } + public static void documentation(DocumentationBuilder doc) { + doc.operation("Layout Operations", id(), name()) + .description("End tag for components / layouts. This operation marks the end" + + "of a component"); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentStart.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentStart.java index 5cfad2521403..32ef5ce8b278 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentStart.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentStart.java @@ -23,14 +23,11 @@ import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.WireBuffer; import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; -import com.android.internal.widget.remotecompose.core.documentation.DocumentedCompanionOperation; import java.util.List; public class ComponentStart implements ComponentStartOperation { - public static final ComponentStart.Companion COMPANION = new ComponentStart.Companion(); - int mType = DEFAULT; float mX; float mY; @@ -73,12 +70,12 @@ public class ComponentStart implements ComponentStartOperation { @Override public void write(WireBuffer buffer) { - Companion.apply(buffer, mType, mComponentId, mWidth, mHeight); + apply(buffer, mType, mComponentId, mWidth, mHeight); } @Override public String toString() { - return "COMPONENT_START (type " + mType + " " + Companion.typeDescription(mType) + return "COMPONENT_START (type " + mType + " " + typeDescription(mType) + ") - (" + mX + ", " + mY + " - " + mWidth + " x " + mHeight + ")"; } @@ -111,83 +108,75 @@ public class ComponentStart implements ComponentStartOperation { public static final int LAYOUT_ROW = 15; public static final int LAYOUT_COLUMN = 16; - public static class Companion implements DocumentedCompanionOperation { - - - public static String typeDescription(int type) { - switch (type) { - case DEFAULT: - return "DEFAULT"; - case ROOT_LAYOUT: - return "ROOT_LAYOUT"; - case LAYOUT: - return "LAYOUT"; - case LAYOUT_CONTENT: - return "CONTENT"; - case SCROLL_CONTENT: - return "SCROLL_CONTENT"; - case BUTTON: - return "BUTTON"; - case CHECKBOX: - return "CHECKBOX"; - case TEXT: - return "TEXT"; - case CURVED_TEXT: - return "CURVED_TEXT"; - case STATE_HOST: - return "STATE_HOST"; - case LOTTIE: - return "LOTTIE"; - case CUSTOM: - return "CUSTOM"; - case IMAGE: - return "IMAGE"; - default: - return "UNKNOWN"; - } + public static String typeDescription(int type) { + switch (type) { + case DEFAULT: + return "DEFAULT"; + case ROOT_LAYOUT: + return "ROOT_LAYOUT"; + case LAYOUT: + return "LAYOUT"; + case LAYOUT_CONTENT: + return "CONTENT"; + case SCROLL_CONTENT: + return "SCROLL_CONTENT"; + case BUTTON: + return "BUTTON"; + case CHECKBOX: + return "CHECKBOX"; + case TEXT: + return "TEXT"; + case CURVED_TEXT: + return "CURVED_TEXT"; + case STATE_HOST: + return "STATE_HOST"; + case LOTTIE: + return "LOTTIE"; + case CUSTOM: + return "CUSTOM"; + case IMAGE: + return "IMAGE"; + default: + return "UNKNOWN"; } + } - @Override - public String name() { - return "ComponentStart"; - } + public static String name() { + return "ComponentStart"; + } - @Override - public int id() { - return Operations.COMPONENT_START; - } + public static int id() { + return Operations.COMPONENT_START; + } - public static void apply(WireBuffer buffer, int type, int componentId, - float width, float height) { - buffer.start(Operations.COMPONENT_START); - buffer.writeInt(type); - buffer.writeInt(componentId); - buffer.writeFloat(width); - buffer.writeFloat(height); - } + public static void apply(WireBuffer buffer, int type, int componentId, + float width, float height) { + buffer.start(Operations.COMPONENT_START); + buffer.writeInt(type); + buffer.writeInt(componentId); + buffer.writeFloat(width); + buffer.writeFloat(height); + } - public static int size() { - return 1 + 4 + 4 + 4; - } + public static int size() { + return 1 + 4 + 4 + 4; + } - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int type = buffer.readInt(); - int componentId = buffer.readInt(); - float width = buffer.readFloat(); - float height = buffer.readFloat(); - operations.add(new ComponentStart(type, componentId, width, height)); - } + public static void read(WireBuffer buffer, List<Operation> operations) { + int type = buffer.readInt(); + int componentId = buffer.readInt(); + float width = buffer.readFloat(); + float height = buffer.readFloat(); + operations.add(new ComponentStart(type, componentId, width, height)); + } - @Override - public void documentation(DocumentationBuilder doc) { - doc.operation("Layout Operations", id(), name()) - .description("Basic component encapsulating draw commands." - + "This is not resizable.") - .field(INT, "TYPE", "Type of components") - .field(INT, "COMPONENT_ID", "unique id for this component") - .field(FLOAT, "WIDTH", "width of the component") - .field(FLOAT, "HEIGHT", "height of the component"); - } + public static void documentation(DocumentationBuilder doc) { + doc.operation("Layout Operations", id(), name()) + .description("Basic component encapsulating draw commands." + + "This is not resizable.") + .field(INT, "TYPE", "Type of components") + .field(INT, "COMPONENT_ID", "unique id for this component") + .field(FLOAT, "WIDTH", "width of the component") + .field(FLOAT, "HEIGHT", "height of the component"); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/DecoratorComponent.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/DecoratorComponent.java index 941666aa90d7..71bf83913cfb 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/DecoratorComponent.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/DecoratorComponent.java @@ -15,6 +15,7 @@ */ package com.android.internal.widget.remotecompose.core.operations.layout; +import com.android.internal.widget.remotecompose.core.CoreDocument; import com.android.internal.widget.remotecompose.core.RemoteContext; /** @@ -23,5 +24,6 @@ import com.android.internal.widget.remotecompose.core.RemoteContext; */ public interface DecoratorComponent { void layout(RemoteContext context, float width, float height); - void onClick(float x, float y); + void onClick(RemoteContext context, CoreDocument document, + Component component, float x, float y); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponent.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponent.java index f198c4a9337b..f4c213159882 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponent.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponent.java @@ -17,7 +17,13 @@ package com.android.internal.widget.remotecompose.core.operations.layout; import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.PaintContext; +import com.android.internal.widget.remotecompose.core.operations.BitmapData; +import com.android.internal.widget.remotecompose.core.operations.MatrixRestore; +import com.android.internal.widget.remotecompose.core.operations.MatrixSave; +import com.android.internal.widget.remotecompose.core.operations.MatrixTranslate; +import com.android.internal.widget.remotecompose.core.operations.TextData; import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ComponentModifiers; +import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ComponentVisibilityOperation; import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.DimensionModifierOperation; import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.HeightModifierOperation; import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ModifierOperation; @@ -56,40 +62,101 @@ public class LayoutComponent extends Component { public float getMarginLeft() { return mMarginLeft; } + public float getMarginRight() { return mMarginRight; } + public float getMarginTop() { return mMarginTop; } + public float getMarginBottom() { return mMarginBottom; } + public float getPaddingLeft() { + return mPaddingLeft; + } + + public float getPaddingTop() { + return mPaddingTop; + } + + public float getPaddingRight() { + return mPaddingRight; + } + + public float getPaddingBottom() { + return mPaddingBottom; + } + + public WidthModifierOperation getWidthModifier() { return mWidthModifier; } + public HeightModifierOperation getHeightModifier() { return mHeightModifier; } + protected LayoutComponentContent mContent = null; + + // Should be removed after ImageLayout is in + private static final boolean USE_IMAGE_TEMP_FIX = true; + public void inflate() { + ArrayList<TextData> data = new ArrayList<>(); for (Operation op : mList) { if (op instanceof LayoutComponentContent) { - ((LayoutComponentContent) op).mParent = this; + mContent = (LayoutComponentContent) op; + mContent.mParent = this; mChildrenComponents.clear(); - ((LayoutComponentContent) op).getComponents(mChildrenComponents); - if (mChildrenComponents.isEmpty()) { - mChildrenComponents.add((Component) op); + LayoutComponentContent content = (LayoutComponentContent) op; + content.getComponents(mChildrenComponents); + if (USE_IMAGE_TEMP_FIX) { + if (mChildrenComponents.isEmpty() && !mContent.mList.isEmpty()) { + CanvasContent canvasContent = + new CanvasContent(-1, 0f, 0f, 0f, 0f, this, -1); + for (Operation opc : mContent.mList) { + if (opc instanceof BitmapData) { + canvasContent.mList.add(opc); + int w = ((BitmapData) opc).getWidth(); + int h = ((BitmapData) opc).getHeight(); + canvasContent.setWidth(w); + canvasContent.setHeight(h); + } else { + if (!((opc instanceof MatrixTranslate) + || (opc instanceof MatrixSave) + || (opc instanceof MatrixRestore))) { + canvasContent.mList.add(opc); + } + } + } + if (!canvasContent.mList.isEmpty()) { + mContent.mList.clear(); + mChildrenComponents.add(canvasContent); + } + } else { + content.getData(data); + } + } else { + content.getData(data); } } else if (op instanceof ModifierOperation) { + if (op instanceof ComponentVisibilityOperation) { + ((ComponentVisibilityOperation) op).setParent(this); + } mComponentModifiers.add((ModifierOperation) op); + } else if (op instanceof TextData) { + data.add((TextData) op); } else { // nothing } } mList.clear(); + mList.addAll(data); mList.add(mComponentModifiers); for (Component c : mChildrenComponents) { c.mParent = this; @@ -146,8 +213,8 @@ public class LayoutComponent extends Component { if (mHeightModifier == null) { mHeightModifier = new HeightModifierOperation(DimensionModifierOperation.Type.WRAP); } - mWidth = computeModifierDefinedWidth(); - mHeight = computeModifierDefinedHeight(); + setWidth(computeModifierDefinedWidth()); + setHeight(computeModifierDefinedHeight()); } @Override @@ -170,6 +237,7 @@ public class LayoutComponent extends Component { context.restore(); } + /** * Traverse the modifiers to compute indicated dimension */ @@ -195,6 +263,27 @@ public class LayoutComponent extends Component { } /** + * Traverse the modifiers to compute padding width + * + * @param padding output start and end padding values + * @return padding width + */ + public float computeModifierDefinedPaddingWidth(float[] padding) { + float s = 0f; + float e = 0f; + for (Operation c : mComponentModifiers.getList()) { + if (c instanceof PaddingModifierOperation) { + PaddingModifierOperation pop = (PaddingModifierOperation) c; + s += pop.getLeft(); + e += pop.getRight(); + } + } + padding[0] = s; + padding[1] = e; + return s + e; + } + + /** * Traverse the modifiers to compute indicated dimension */ public float computeModifierDefinedHeight() { @@ -217,4 +306,26 @@ public class LayoutComponent extends Component { } return t + h + b; } + + /** + * Traverse the modifiers to compute padding height + * + * @param padding output top and bottom padding values + * @return padding height + */ + public float computeModifierDefinedPaddingHeight(float[] padding) { + float t = 0f; + float b = 0f; + for (Operation c : mComponentModifiers.getList()) { + if (c instanceof PaddingModifierOperation) { + PaddingModifierOperation pop = (PaddingModifierOperation) c; + t += pop.getTop(); + b += pop.getBottom(); + } + } + padding[0] = t; + padding[1] = b; + return t + b; + } + } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponentContent.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponentContent.java index 769ff6ac3e7d..5b3b54d3c423 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponentContent.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponentContent.java @@ -15,11 +15,12 @@ */ package com.android.internal.widget.remotecompose.core.operations.layout; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.WireBuffer; import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; -import com.android.internal.widget.remotecompose.core.documentation.DocumentedCompanionOperation; import java.util.List; @@ -28,41 +29,44 @@ import java.util.List; */ public class LayoutComponentContent extends Component implements ComponentStartOperation { - public static final LayoutComponentContent.Companion COMPANION = - new LayoutComponentContent.Companion(); - public LayoutComponentContent(int componentId, float x, float y, float width, float height, Component parent, int animationId) { super(parent, componentId, animationId, x, y, width, height); } - public static class Companion implements DocumentedCompanionOperation { - @Override - public String name() { - return "LayoutContent"; - } + public static String name() { + return "LayoutContent"; + } + + public static int id() { + return Operations.LAYOUT_CONTENT; + } + + @Override protected String getSerializedName() { + return "CONTENT"; + } - @Override - public int id() { - return Operations.LAYOUT_CONTENT; - } + public static void apply(WireBuffer buffer, int componentId) { + buffer.start(Operations.LAYOUT_CONTENT); + buffer.writeInt(componentId); + } - public void apply(WireBuffer buffer) { - buffer.start(Operations.LAYOUT_CONTENT); - } + public static void read(WireBuffer buffer, List<Operation> operations) { + int componentId = buffer.readInt(); + operations.add(new LayoutComponentContent( + componentId, 0, 0, 0, 0, null, -1)); + } - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - operations.add(new LayoutComponentContent( - -1, 0, 0, 0, 0, null, -1)); - } + public static void documentation(DocumentationBuilder doc) { + doc.operation("Layout Operations", id(), name()) + .field(INT, "COMPONENT_ID", "unique id for this component") + .description("Container for components. BoxLayout, RowLayout and ColumnLayout " + + "expects a LayoutComponentContent as a child, encapsulating the " + + "components that needs to be laid out."); + } - @Override - public void documentation(DocumentationBuilder doc) { - doc.operation("Layout Operations", id(), name()) - .description("Container for components. BoxLayout, RowLayout and ColumnLayout " - + "expects a LayoutComponentContent as a child, encapsulating the " - + "components that needs to be laid out."); - } + @Override + public void write(WireBuffer buffer) { + apply(buffer, mComponentId); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/RootLayoutComponent.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/RootLayoutComponent.java index dc13768992ce..bf1a4963d4c4 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/RootLayoutComponent.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/RootLayoutComponent.java @@ -15,14 +15,16 @@ */ package com.android.internal.widget.remotecompose.core.operations.layout; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; import com.android.internal.widget.remotecompose.core.PaintOperation; import com.android.internal.widget.remotecompose.core.RemoteContext; +import com.android.internal.widget.remotecompose.core.SerializableToString; import com.android.internal.widget.remotecompose.core.WireBuffer; import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; -import com.android.internal.widget.remotecompose.core.documentation.DocumentedCompanionOperation; import com.android.internal.widget.remotecompose.core.operations.layout.measure.Measurable; import com.android.internal.widget.remotecompose.core.operations.layout.measure.MeasurePass; import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ComponentModifiers; @@ -34,10 +36,6 @@ import java.util.List; * Represents the root layout component. Entry point to the component tree layout/paint. */ public class RootLayoutComponent extends Component implements ComponentStartOperation { - - public static final RootLayoutComponent.Companion COMPANION = - new RootLayoutComponent.Companion(); - int mCurrentId = -1; public RootLayoutComponent(int componentId, float x, float y, @@ -52,7 +50,8 @@ public class RootLayoutComponent extends Component implements ComponentStartOper @Override public String toString() { - return "ROOT (" + mX + ", " + mY + " - " + mWidth + " x " + mHeight + ") " + mVisibility; + return "ROOT " + mComponentId + " (" + mX + ", " + mY + " - " + + mWidth + " x " + mHeight + ") " + mVisibility; } @Override @@ -61,18 +60,22 @@ public class RootLayoutComponent extends Component implements ComponentStartOper + "] = [" + mX + ", " + mY + ", " + mWidth + ", " + mHeight + "] " + mVisibility); } - public int getNextId() { - mCurrentId--; - return mCurrentId; - } - - public void assignIds() { + /** + * Traverse the hierarchy and assign generated ids to component without ids. + * Most components would already have ids assigned during the document creation, but this + * allow us to take care of any components added during the inflation. + * + * @param lastId the last known generated id + */ + public void assignIds(int lastId) { + mCurrentId = lastId; assignId(this); } - void assignId(Component component) { + private void assignId(Component component) { if (component.mComponentId == -1) { - component.mComponentId = getNextId(); + mCurrentId--; + component.mComponentId = mCurrentId; } for (Operation op : component.mList) { if (op instanceof Component) { @@ -135,39 +138,42 @@ public class RootLayoutComponent extends Component implements ComponentStartOper for (Operation c : component.mList) { if (c instanceof ComponentModifiers) { ((ComponentModifiers) c).serializeToString(indent + 1, serializer); - } - if (c instanceof Component) { + } else if (c instanceof Component) { displayHierarchy((Component) c, indent + 1, serializer); + } else if (c instanceof SerializableToString) { + ((SerializableToString) c).serializeToString(indent + 1, serializer); } } } - public static class Companion implements DocumentedCompanionOperation { - @Override - public String name() { - return "RootLayout"; - } + public static String name() { + return "RootLayout"; + } - @Override - public int id() { - return Operations.LAYOUT_ROOT; - } + public static int id() { + return Operations.LAYOUT_ROOT; + } - public void apply(WireBuffer buffer) { - buffer.start(Operations.LAYOUT_ROOT); - } + public static void apply(WireBuffer buffer, int componentId) { + buffer.start(Operations.LAYOUT_ROOT); + buffer.writeInt(componentId); + } - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - operations.add(new RootLayoutComponent( - -1, 0, 0, 0, 0, null, -1)); - } + public static void read(WireBuffer buffer, List<Operation> operations) { + int componentId = buffer.readInt(); + operations.add(new RootLayoutComponent( + componentId, 0, 0, 0, 0, null, -1)); + } - @Override - public void documentation(DocumentationBuilder doc) { - doc.operation("Layout Operations", id(), name()) - .description("Root element for a document. Other components / layout managers " - + "are children in the component tree starting from this Root component."); - } + public static void documentation(DocumentationBuilder doc) { + doc.operation("Layout Operations", id(), name()) + .field(INT, "COMPONENT_ID", "unique id for this component") + .description("Root element for a document. Other components / layout managers " + + "are children in the component tree starting from this Root component."); + } + + @Override + public void write(WireBuffer buffer) { + apply(buffer, mComponentId); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimateMeasure.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimateMeasure.java index 7c6bef425eef..1ada733e2cb2 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimateMeasure.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimateMeasure.java @@ -75,7 +75,7 @@ public class AnimateMeasure { mP = Math.min(elapsed / (float) mDuration, 1f); //mP = motionEasing.get(mP); mVp = Math.min(elapsed / (float) mDurationVisibilityChange, 1f); - mVp = mVisibilityEasing.get(mVp); + // mVp = mVisibilityEasing.get(mVp); } public PaintBundle paint = new PaintBundle(); @@ -101,7 +101,6 @@ public class AnimateMeasure { } } - mComponent.mVisibility = mTarget.getVisibility(); if (mOriginal.getVisibility() != mTarget.getVisibility()) { if (mTarget.getVisibility() == Component.Visibility.GONE) { switch (mExitAnimation) { @@ -256,7 +255,7 @@ public class AnimateMeasure { } else { mComponent.paintingComponent(context); } - } else { + } else if (mTarget.getVisibility() == Component.Visibility.VISIBLE) { mComponent.paintingComponent(context); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimationSpec.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimationSpec.java index 386d365ec033..0f7db36e8e01 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimationSpec.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimationSpec.java @@ -15,11 +15,13 @@ */ package com.android.internal.widget.remotecompose.core.operations.layout.animation; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import com.android.internal.widget.remotecompose.core.operations.utilities.easing.GeneralEasing; import java.util.List; @@ -28,9 +30,6 @@ import java.util.List; * Basic component animation spec */ public class AnimationSpec implements Operation { - - public static final AnimationSpec.Companion COMPANION = new AnimationSpec.Companion(); - int mAnimationId = -1; int mMotionDuration = 300; int mMotionEasingType = GeneralEasing.CUBIC_STANDARD; @@ -103,7 +102,7 @@ public class AnimationSpec implements Operation { @Override public void write(WireBuffer buffer) { - Companion.apply(buffer, mAnimationId, mMotionDuration, mMotionEasingType, + apply(buffer, mAnimationId, mMotionDuration, mMotionEasingType, mVisibilityDuration, mVisibilityEasingType, mEnterAnimation, mExitAnimation); } @@ -117,70 +116,77 @@ public class AnimationSpec implements Operation { return (indent != null ? indent : "") + toString(); } - public static class Companion implements CompanionOperation { - @Override - public String name() { - return "AnimationSpec"; - } + public static String name() { + return "AnimationSpec"; + } - @Override - public int id() { - return Operations.ANIMATION_SPEC; - } + public static int id() { + return Operations.ANIMATION_SPEC; + } - public static int animationToInt(ANIMATION animation) { - return animation.ordinal(); - } + public static int animationToInt(ANIMATION animation) { + return animation.ordinal(); + } - public static ANIMATION intToAnimation(int value) { - switch (value) { - case 0: - return ANIMATION.FADE_IN; - case 1: - return ANIMATION.FADE_OUT; - case 2: - return ANIMATION.SLIDE_LEFT; - case 3: - return ANIMATION.SLIDE_RIGHT; - case 4: - return ANIMATION.SLIDE_TOP; - case 5: - return ANIMATION.SLIDE_BOTTOM; - case 6: - return ANIMATION.ROTATE; - case 7: - return ANIMATION.PARTICLE; - default: - return ANIMATION.FADE_IN; - } + public static ANIMATION intToAnimation(int value) { + switch (value) { + case 0: + return ANIMATION.FADE_IN; + case 1: + return ANIMATION.FADE_OUT; + case 2: + return ANIMATION.SLIDE_LEFT; + case 3: + return ANIMATION.SLIDE_RIGHT; + case 4: + return ANIMATION.SLIDE_TOP; + case 5: + return ANIMATION.SLIDE_BOTTOM; + case 6: + return ANIMATION.ROTATE; + case 7: + return ANIMATION.PARTICLE; + default: + return ANIMATION.FADE_IN; } + } - public static void apply(WireBuffer buffer, int animationId, int motionDuration, - int motionEasingType, int visibilityDuration, - int visibilityEasingType, ANIMATION enterAnimation, - ANIMATION exitAnimation) { - buffer.start(Operations.ANIMATION_SPEC); - buffer.writeInt(animationId); - buffer.writeInt(motionDuration); - buffer.writeInt(motionEasingType); - buffer.writeInt(visibilityDuration); - buffer.writeInt(visibilityEasingType); - buffer.writeInt(animationToInt(enterAnimation)); - buffer.writeInt(animationToInt(exitAnimation)); - } + public static void apply(WireBuffer buffer, int animationId, int motionDuration, + int motionEasingType, int visibilityDuration, + int visibilityEasingType, ANIMATION enterAnimation, + ANIMATION exitAnimation) { + buffer.start(Operations.ANIMATION_SPEC); + buffer.writeInt(animationId); + buffer.writeInt(motionDuration); + buffer.writeInt(motionEasingType); + buffer.writeInt(visibilityDuration); + buffer.writeInt(visibilityEasingType); + buffer.writeInt(animationToInt(enterAnimation)); + buffer.writeInt(animationToInt(exitAnimation)); + } + + public static void read(WireBuffer buffer, List<Operation> operations) { + int animationId = buffer.readInt(); + int motionDuration = buffer.readInt(); + int motionEasingType = buffer.readInt(); + int visibilityDuration = buffer.readInt(); + int visibilityEasingType = buffer.readInt(); + ANIMATION enterAnimation = intToAnimation(buffer.readInt()); + ANIMATION exitAnimation = intToAnimation(buffer.readInt()); + AnimationSpec op = new AnimationSpec(animationId, motionDuration, motionEasingType, + visibilityDuration, visibilityEasingType, enterAnimation, exitAnimation); + operations.add(op); + } + public static void documentation(DocumentationBuilder doc) { + doc.operation("Layout Operations", + id(), + name()) + .description("define the animation") + .field(INT, "animationId", "") + .field(INT, "motionDuration", "") + .field(INT, "motionEasingType", "") + .field(INT, "visibilityDuration", "") + .field(INT, "visibilityEasingType", ""); - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int animationId = buffer.readInt(); - int motionDuration = buffer.readInt(); - int motionEasingType = buffer.readInt(); - int visibilityDuration = buffer.readInt(); - int visibilityEasingType = buffer.readInt(); - ANIMATION enterAnimation = intToAnimation(buffer.readInt()); - ANIMATION exitAnimation = intToAnimation(buffer.readInt()); - AnimationSpec op = new AnimationSpec(animationId, motionDuration, motionEasingType, - visibilityDuration, visibilityEasingType, enterAnimation, exitAnimation); - operations.add(op); - } } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/BoxLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/BoxLayout.java index fea8dd2de209..88a49a666cd7 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/BoxLayout.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/BoxLayout.java @@ -22,7 +22,6 @@ import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; import com.android.internal.widget.remotecompose.core.WireBuffer; import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; -import com.android.internal.widget.remotecompose.core.documentation.DocumentedCompanionOperation; import com.android.internal.widget.remotecompose.core.operations.layout.Component; import com.android.internal.widget.remotecompose.core.operations.layout.ComponentStartOperation; import com.android.internal.widget.remotecompose.core.operations.layout.measure.ComponentMeasure; @@ -42,7 +41,6 @@ public class BoxLayout extends LayoutManager implements ComponentStartOperation public static final int TOP = 4; public static final int BOTTOM = 5; - public static final BoxLayout.Companion COMPANION = new BoxLayout.Companion(); int mHorizontalPositioning; int mVerticalPositioning; @@ -127,63 +125,63 @@ public class BoxLayout extends LayoutManager implements ComponentStartOperation } m.setX(tx); m.setY(ty); - m.setVisibility(child.mVisibility); } } - public static class Companion implements DocumentedCompanionOperation { - @Override - public String name() { - return "BoxLayout"; - } + public static String name() { + return "BoxLayout"; + } - @Override - public int id() { - return Operations.LAYOUT_BOX; - } + public static int id() { + return Operations.LAYOUT_BOX; + } - public void apply(WireBuffer buffer, int componentId, int animationId, - int horizontalPositioning, int verticalPositioning) { - buffer.start(Operations.LAYOUT_BOX); - buffer.writeInt(componentId); - buffer.writeInt(animationId); - buffer.writeInt(horizontalPositioning); - buffer.writeInt(verticalPositioning); - } + public static void apply(WireBuffer buffer, int componentId, int animationId, + int horizontalPositioning, int verticalPositioning) { + buffer.start(Operations.LAYOUT_BOX); + buffer.writeInt(componentId); + buffer.writeInt(animationId); + buffer.writeInt(horizontalPositioning); + buffer.writeInt(verticalPositioning); + } - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int componentId = buffer.readInt(); - int animationId = buffer.readInt(); - int horizontalPositioning = buffer.readInt(); - int verticalPositioning = buffer.readInt(); - operations.add(new BoxLayout(null, componentId, animationId, - horizontalPositioning, verticalPositioning)); - } + public static void read(WireBuffer buffer, List<Operation> operations) { + int componentId = buffer.readInt(); + int animationId = buffer.readInt(); + int horizontalPositioning = buffer.readInt(); + int verticalPositioning = buffer.readInt(); + operations.add(new BoxLayout(null, componentId, animationId, + horizontalPositioning, verticalPositioning)); + } - @Override - public void documentation(DocumentationBuilder doc) { - doc.operation("Layout Operations", id(), name()) + public static void documentation(DocumentationBuilder doc) { + doc.operation("Layout Operations", id(), name()) .description("Box layout implementation.\n\n" - + "Child components are laid out independently from one another,\n" - + " and painted in their hierarchy order (first children drawn" - + "before the latter). Horizontal and Vertical positioning" - + "are supported.") + + "Child components are laid out independently from one another,\n" + + " and painted in their hierarchy order (first children drawn" + + "before the latter). Horizontal and Vertical positioning" + + "are supported.") .examplesDimension(150, 100) .exampleImage("Top", "layout-BoxLayout-start-top.png") .exampleImage("Center", "layout-BoxLayout-center-center.png") .exampleImage("Bottom", "layout-BoxLayout-end-bottom.png") .field(INT, "COMPONENT_ID", "unique id for this component") .field(INT, "ANIMATION_ID", "id used to match components," - + " for animation purposes") + + " for animation purposes") .field(INT, "HORIZONTAL_POSITIONING", "horizontal positioning value") - .possibleValues("START", BoxLayout.START) - .possibleValues("CENTER", BoxLayout.CENTER) - .possibleValues("END", BoxLayout.END) + .possibleValues("START", BoxLayout.START) + .possibleValues("CENTER", BoxLayout.CENTER) + .possibleValues("END", BoxLayout.END) .field(INT, "VERTICAL_POSITIONING", "vertical positioning value") - .possibleValues("TOP", BoxLayout.TOP) - .possibleValues("CENTER", BoxLayout.CENTER) - .possibleValues("BOTTOM", BoxLayout.BOTTOM); - } + .possibleValues("TOP", BoxLayout.TOP) + .possibleValues("CENTER", BoxLayout.CENTER) + .possibleValues("BOTTOM", BoxLayout.BOTTOM); + } + + + @Override + public void write(WireBuffer buffer) { + apply(buffer, mComponentId, mAnimationId, + mHorizontalPositioning, mVerticalPositioning); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/CanvasLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/CanvasLayout.java new file mode 100644 index 000000000000..bce7a77abb36 --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/CanvasLayout.java @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget.remotecompose.core.operations.layout.managers; + +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; + +import com.android.internal.widget.remotecompose.core.Operation; +import com.android.internal.widget.remotecompose.core.Operations; +import com.android.internal.widget.remotecompose.core.PaintContext; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; +import com.android.internal.widget.remotecompose.core.operations.layout.Component; +import com.android.internal.widget.remotecompose.core.operations.layout.measure.ComponentMeasure; +import com.android.internal.widget.remotecompose.core.operations.layout.measure.MeasurePass; + +import java.util.List; + +public class CanvasLayout extends BoxLayout { + public CanvasLayout(Component parent, int componentId, int animationId, + float x, float y, float width, float height) { + super(parent, componentId, animationId, x, y, width, height, 0, 0); + } + + public CanvasLayout(Component parent, int componentId, int animationId) { + this(parent, componentId, animationId, 0, 0, 0, 0); + } + + @Override + public String toString() { + return "CANVAS [" + mComponentId + ":" + mAnimationId + "] (" + mX + ", " + + mY + " - " + mWidth + " x " + mHeight + ") " + mVisibility; + } + + protected String getSerializedName() { + return "CANVAS"; + } + + public static String name() { + return "CanvasLayout"; + } + + public static int id() { + return Operations.LAYOUT_CANVAS; + } + + public static void apply(WireBuffer buffer, int componentId, int animationId) { + buffer.start(Operations.LAYOUT_CANVAS); + buffer.writeInt(componentId); + buffer.writeInt(animationId); + } + + public static void read(WireBuffer buffer, List<Operation> operations) { + int componentId = buffer.readInt(); + int animationId = buffer.readInt(); + operations.add(new CanvasLayout(null, componentId, animationId)); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Layout Operations", id(), name()) + .description("Canvas implementation. Encapsulate draw operations.\n\n") + .field(INT, "COMPONENT_ID", "unique id for this component") + .field(INT, "ANIMATION_ID", "id used to match components," + + " for animation purposes"); + } + + @Override + public void internalLayoutMeasure(PaintContext context, + MeasurePass measure) { + ComponentMeasure selfMeasure = measure.get(this); + float selfWidth = selfMeasure.getW() - mPaddingLeft - mPaddingRight; + float selfHeight = selfMeasure.getH() - mPaddingTop - mPaddingBottom; + for (Component child : mChildrenComponents) { + ComponentMeasure m = measure.get(child); + m.setX(0f); + m.setY(0f); + m.setW(selfWidth); + m.setH(selfHeight); + } + } + + @Override + public void write(WireBuffer buffer) { + apply(buffer, mComponentId, mAnimationId); + } +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/ColumnLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/ColumnLayout.java index a1a2de5302b8..48d966ebe9a7 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/ColumnLayout.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/ColumnLayout.java @@ -23,7 +23,6 @@ import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; import com.android.internal.widget.remotecompose.core.WireBuffer; import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; -import com.android.internal.widget.remotecompose.core.documentation.DocumentedCompanionOperation; import com.android.internal.widget.remotecompose.core.operations.layout.Component; import com.android.internal.widget.remotecompose.core.operations.layout.ComponentStartOperation; import com.android.internal.widget.remotecompose.core.operations.layout.LayoutComponent; @@ -48,8 +47,6 @@ public class ColumnLayout extends LayoutManager implements ComponentStartOperati public static final int SPACE_EVENLY = 7; public static final int SPACE_AROUND = 8; - public static final ColumnLayout.Companion COMPANION = new ColumnLayout.Companion(); - int mHorizontalPositioning; int mVerticalPositioning; float mSpacedBy = 0f; @@ -64,7 +61,7 @@ public class ColumnLayout extends LayoutManager implements ComponentStartOperati } public ColumnLayout(Component parent, int componentId, int animationId, - int horizontalPositioning, int verticalPositioning, float spacedBy) { + int horizontalPositioning, int verticalPositioning, float spacedBy) { this(parent, componentId, animationId, 0, 0, 0, 0, horizontalPositioning, verticalPositioning, spacedBy); } @@ -214,7 +211,6 @@ public class ColumnLayout extends LayoutManager implements ComponentStartOperati } childMeasure.setX(tx); childMeasure.setY(ty); - childMeasure.setVisibility(child.mVisibility); ty += childMeasure.getH(); if (mVerticalPositioning == SPACE_BETWEEN || mVerticalPositioning == SPACE_AROUND @@ -226,66 +222,66 @@ public class ColumnLayout extends LayoutManager implements ComponentStartOperati DebugLog.e(); } - public static class Companion implements DocumentedCompanionOperation { - @Override - public String name() { - return "ColumnLayout"; - } + public static String name() { + return "ColumnLayout"; + } - @Override - public int id() { - return Operations.LAYOUT_COLUMN; - } + public static int id() { + return Operations.LAYOUT_COLUMN; + } - public void apply(WireBuffer buffer, int componentId, int animationId, - int horizontalPositioning, int verticalPositioning, float spacedBy) { - buffer.start(Operations.LAYOUT_COLUMN); - buffer.writeInt(componentId); - buffer.writeInt(animationId); - buffer.writeInt(horizontalPositioning); - buffer.writeInt(verticalPositioning); - buffer.writeFloat(spacedBy); - } + public static void apply(WireBuffer buffer, int componentId, int animationId, + int horizontalPositioning, int verticalPositioning, float spacedBy) { + buffer.start(Operations.LAYOUT_COLUMN); + buffer.writeInt(componentId); + buffer.writeInt(animationId); + buffer.writeInt(horizontalPositioning); + buffer.writeInt(verticalPositioning); + buffer.writeFloat(spacedBy); + } - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int componentId = buffer.readInt(); - int animationId = buffer.readInt(); - int horizontalPositioning = buffer.readInt(); - int verticalPositioning = buffer.readInt(); - float spacedBy = buffer.readFloat(); - operations.add(new ColumnLayout(null, componentId, animationId, - horizontalPositioning, verticalPositioning, spacedBy)); - } + public static void read(WireBuffer buffer, List<Operation> operations) { + int componentId = buffer.readInt(); + int animationId = buffer.readInt(); + int horizontalPositioning = buffer.readInt(); + int verticalPositioning = buffer.readInt(); + float spacedBy = buffer.readFloat(); + operations.add(new ColumnLayout(null, componentId, animationId, + horizontalPositioning, verticalPositioning, spacedBy)); + } - @Override - public void documentation(DocumentationBuilder doc) { - doc.operation("Layout Operations", id(), name()) - .description("Column layout implementation, positioning components one" - + " after the other vertically.\n\n" - + "It supports weight and horizontal/vertical positioning.") - .examplesDimension(100, 400) - .exampleImage("Top", "layout-ColumnLayout-start-top.png") - .exampleImage("Center", "layout-ColumnLayout-start-center.png") - .exampleImage("Bottom", "layout-ColumnLayout-start-bottom.png") - .exampleImage("SpaceEvenly", "layout-ColumnLayout-start-space-evenly.png") - .exampleImage("SpaceAround", "layout-ColumnLayout-start-space-around.png") - .exampleImage("SpaceBetween", "layout-ColumnLayout-start-space-between.png") - .field(INT, "COMPONENT_ID", "unique id for this component") - .field(INT, "ANIMATION_ID", "id used to match components," - + " for animation purposes") - .field(INT, "HORIZONTAL_POSITIONING", "horizontal positioning value") - .possibleValues("START", ColumnLayout.START) - .possibleValues("CENTER", ColumnLayout.CENTER) - .possibleValues("END", ColumnLayout.END) - .field(INT, "VERTICAL_POSITIONING", "vertical positioning value") - .possibleValues("TOP", ColumnLayout.TOP) - .possibleValues("CENTER", ColumnLayout.CENTER) - .possibleValues("BOTTOM", ColumnLayout.BOTTOM) - .possibleValues("SPACE_BETWEEN", ColumnLayout.SPACE_BETWEEN) - .possibleValues("SPACE_EVENLY", ColumnLayout.SPACE_EVENLY) - .possibleValues("SPACE_AROUND", ColumnLayout.SPACE_AROUND) - .field(FLOAT, "SPACED_BY", "Horizontal spacing between components"); - } + public static void documentation(DocumentationBuilder doc) { + doc.operation("Layout Operations", id(), name()) + .description("Column layout implementation, positioning components one" + + " after the other vertically.\n\n" + + "It supports weight and horizontal/vertical positioning.") + .examplesDimension(100, 400) + .exampleImage("Top", "layout-ColumnLayout-start-top.png") + .exampleImage("Center", "layout-ColumnLayout-start-center.png") + .exampleImage("Bottom", "layout-ColumnLayout-start-bottom.png") + .exampleImage("SpaceEvenly", "layout-ColumnLayout-start-space-evenly.png") + .exampleImage("SpaceAround", "layout-ColumnLayout-start-space-around.png") + .exampleImage("SpaceBetween", "layout-ColumnLayout-start-space-between.png") + .field(INT, "COMPONENT_ID", "unique id for this component") + .field(INT, "ANIMATION_ID", "id used to match components," + + " for animation purposes") + .field(INT, "HORIZONTAL_POSITIONING", "horizontal positioning value") + .possibleValues("START", ColumnLayout.START) + .possibleValues("CENTER", ColumnLayout.CENTER) + .possibleValues("END", ColumnLayout.END) + .field(INT, "VERTICAL_POSITIONING", "vertical positioning value") + .possibleValues("TOP", ColumnLayout.TOP) + .possibleValues("CENTER", ColumnLayout.CENTER) + .possibleValues("BOTTOM", ColumnLayout.BOTTOM) + .possibleValues("SPACE_BETWEEN", ColumnLayout.SPACE_BETWEEN) + .possibleValues("SPACE_EVENLY", ColumnLayout.SPACE_EVENLY) + .possibleValues("SPACE_AROUND", ColumnLayout.SPACE_AROUND) + .field(FLOAT, "SPACED_BY", "Horizontal spacing between components"); + } + + @Override + public void write(WireBuffer buffer) { + apply(buffer, mComponentId, mAnimationId, + mHorizontalPositioning, mVerticalPositioning, mSpacedBy); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/LayoutManager.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/LayoutManager.java index 48906837ef94..3a366172a51f 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/LayoutManager.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/LayoutManager.java @@ -109,12 +109,22 @@ public abstract class LayoutManager extends LayoutComponent implements Measurabl if (!hasWrap) { computeSize(context, 0f, measuredWidth, 0f, measuredHeight, measure); } + + if (mContent != null) { + ComponentMeasure cm = measure.get(mContent); + cm.setX(0f); + cm.setY(0f); + cm.setW(measuredWidth); + cm.setH(measuredHeight); + } + measuredWidth += mMarginLeft + mMarginRight; measuredHeight += mMarginTop + mMarginBottom; ComponentMeasure m = measure.get(this); m.setW(measuredWidth); m.setH(measuredHeight); + m.setVisibility(mScheduledVisibility); internalLayoutMeasure(context, measure); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/RowLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/RowLayout.java index 07e2ea186ca5..5e452f363c06 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/RowLayout.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/RowLayout.java @@ -23,7 +23,6 @@ import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; import com.android.internal.widget.remotecompose.core.WireBuffer; import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; -import com.android.internal.widget.remotecompose.core.documentation.DocumentedCompanionOperation; import com.android.internal.widget.remotecompose.core.operations.layout.Component; import com.android.internal.widget.remotecompose.core.operations.layout.ComponentStartOperation; import com.android.internal.widget.remotecompose.core.operations.layout.LayoutComponent; @@ -48,8 +47,6 @@ public class RowLayout extends LayoutManager implements ComponentStartOperation public static final int SPACE_EVENLY = 7; public static final int SPACE_AROUND = 8; - public static final RowLayout.Companion COMPANION = new RowLayout.Companion(); - int mHorizontalPositioning; int mVerticalPositioning; float mSpacedBy = 0f; @@ -68,6 +65,7 @@ public class RowLayout extends LayoutManager implements ComponentStartOperation this(parent, componentId, animationId, 0, 0, 0, 0, horizontalPositioning, verticalPositioning, spacedBy); } + @Override public String toString() { return "ROW [" + mComponentId + ":" + mAnimationId + "] (" + mX + ", " @@ -217,7 +215,6 @@ public class RowLayout extends LayoutManager implements ComponentStartOperation } childMeasure.setX(tx); childMeasure.setY(ty); - childMeasure.setVisibility(child.mVisibility); tx += childMeasure.getW(); if (mHorizontalPositioning == SPACE_BETWEEN || mHorizontalPositioning == SPACE_AROUND @@ -229,66 +226,66 @@ public class RowLayout extends LayoutManager implements ComponentStartOperation DebugLog.e(); } - public static class Companion implements DocumentedCompanionOperation { - @Override - public String name() { - return "RowLayout"; - } + public static String name() { + return "RowLayout"; + } - @Override - public int id() { - return Operations.LAYOUT_ROW; - } + public static int id() { + return Operations.LAYOUT_ROW; + } - public void apply(WireBuffer buffer, int componentId, int animationId, - int horizontalPositioning, int verticalPositioning, float spacedBy) { - buffer.start(Operations.LAYOUT_ROW); - buffer.writeInt(componentId); - buffer.writeInt(animationId); - buffer.writeInt(horizontalPositioning); - buffer.writeInt(verticalPositioning); - buffer.writeFloat(spacedBy); - } + public static void apply(WireBuffer buffer, int componentId, int animationId, + int horizontalPositioning, int verticalPositioning, float spacedBy) { + buffer.start(Operations.LAYOUT_ROW); + buffer.writeInt(componentId); + buffer.writeInt(animationId); + buffer.writeInt(horizontalPositioning); + buffer.writeInt(verticalPositioning); + buffer.writeFloat(spacedBy); + } - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int componentId = buffer.readInt(); - int animationId = buffer.readInt(); - int horizontalPositioning = buffer.readInt(); - int verticalPositioning = buffer.readInt(); - float spacedBy = buffer.readFloat(); - operations.add(new RowLayout(null, componentId, animationId, - horizontalPositioning, verticalPositioning, spacedBy)); - } + public static void read(WireBuffer buffer, List<Operation> operations) { + int componentId = buffer.readInt(); + int animationId = buffer.readInt(); + int horizontalPositioning = buffer.readInt(); + int verticalPositioning = buffer.readInt(); + float spacedBy = buffer.readFloat(); + operations.add(new RowLayout(null, componentId, animationId, + horizontalPositioning, verticalPositioning, spacedBy)); + } - @Override - public void documentation(DocumentationBuilder doc) { - doc.operation("Layout Operations", id(), name()) - .description("Row layout implementation, positioning components one" - + " after the other horizontally.\n\n" - + "It supports weight and horizontal/vertical positioning.") - .examplesDimension(400, 100) - .exampleImage("Start", "layout-RowLayout-start-top.png") - .exampleImage("Center", "layout-RowLayout-center-top.png") - .exampleImage("End", "layout-RowLayout-end-top.png") - .exampleImage("SpaceEvenly", "layout-RowLayout-space-evenly-top.png") - .exampleImage("SpaceAround", "layout-RowLayout-space-around-top.png") - .exampleImage("SpaceBetween", "layout-RowLayout-space-between-top.png") - .field(INT, "COMPONENT_ID", "unique id for this component") - .field(INT, "ANIMATION_ID", "id used to match components," - + " for animation purposes") - .field(INT, "HORIZONTAL_POSITIONING", "horizontal positioning value") - .possibleValues("START", RowLayout.START) - .possibleValues("CENTER", RowLayout.CENTER) - .possibleValues("END", RowLayout.END) - .possibleValues("SPACE_BETWEEN", RowLayout.SPACE_BETWEEN) - .possibleValues("SPACE_EVENLY", RowLayout.SPACE_EVENLY) - .possibleValues("SPACE_AROUND", RowLayout.SPACE_AROUND) - .field(INT, "VERTICAL_POSITIONING", "vertical positioning value") - .possibleValues("TOP", RowLayout.TOP) - .possibleValues("CENTER", RowLayout.CENTER) - .possibleValues("BOTTOM", RowLayout.BOTTOM) - .field(FLOAT, "SPACED_BY", "Horizontal spacing between components"); - } + public static void documentation(DocumentationBuilder doc) { + doc.operation("Layout Operations", id(), name()) + .description("Row layout implementation, positioning components one" + + " after the other horizontally.\n\n" + + "It supports weight and horizontal/vertical positioning.") + .examplesDimension(400, 100) + .exampleImage("Start", "layout-RowLayout-start-top.png") + .exampleImage("Center", "layout-RowLayout-center-top.png") + .exampleImage("End", "layout-RowLayout-end-top.png") + .exampleImage("SpaceEvenly", "layout-RowLayout-space-evenly-top.png") + .exampleImage("SpaceAround", "layout-RowLayout-space-around-top.png") + .exampleImage("SpaceBetween", "layout-RowLayout-space-between-top.png") + .field(INT, "COMPONENT_ID", "unique id for this component") + .field(INT, "ANIMATION_ID", "id used to match components," + + " for animation purposes") + .field(INT, "HORIZONTAL_POSITIONING", "horizontal positioning value") + .possibleValues("START", RowLayout.START) + .possibleValues("CENTER", RowLayout.CENTER) + .possibleValues("END", RowLayout.END) + .possibleValues("SPACE_BETWEEN", RowLayout.SPACE_BETWEEN) + .possibleValues("SPACE_EVENLY", RowLayout.SPACE_EVENLY) + .possibleValues("SPACE_AROUND", RowLayout.SPACE_AROUND) + .field(INT, "VERTICAL_POSITIONING", "vertical positioning value") + .possibleValues("TOP", RowLayout.TOP) + .possibleValues("CENTER", RowLayout.CENTER) + .possibleValues("BOTTOM", RowLayout.BOTTOM) + .field(FLOAT, "SPACED_BY", "Horizontal spacing between components"); + } + + @Override + public void write(WireBuffer buffer) { + apply(buffer, mComponentId, mAnimationId, + mHorizontalPositioning, mVerticalPositioning, mSpacedBy); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/TextLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/TextLayout.java new file mode 100644 index 000000000000..23705003179c --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/TextLayout.java @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget.remotecompose.core.operations.layout.managers; + +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; + +import com.android.internal.widget.remotecompose.core.Operation; +import com.android.internal.widget.remotecompose.core.Operations; +import com.android.internal.widget.remotecompose.core.PaintContext; +import com.android.internal.widget.remotecompose.core.RemoteContext; +import com.android.internal.widget.remotecompose.core.VariableSupport; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; +import com.android.internal.widget.remotecompose.core.operations.layout.Component; +import com.android.internal.widget.remotecompose.core.operations.layout.ComponentStartOperation; +import com.android.internal.widget.remotecompose.core.operations.layout.measure.MeasurePass; +import com.android.internal.widget.remotecompose.core.operations.layout.measure.Size; +import com.android.internal.widget.remotecompose.core.operations.paint.PaintBundle; +import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer; + +import java.util.List; + +/** + * Text component, referencing a text id + */ +public class TextLayout extends LayoutManager implements ComponentStartOperation, VariableSupport { + + private static final boolean DEBUG = false; + private int mTextId = -1; + private int mColor = 0; + private float mFontSize = 16f; + private int mFontStyle = 0; + private float mFontWeight = 400f; + private int mFontFamilyId = -1; + + private int mType = -1; + private float mTextX; + private float mTextY; + + private String mCachedString = ""; + + @Override + public void registerListening(RemoteContext context) { + if (mTextId != -1) { + context.listensTo(mTextId, this); + } + } + + @Override + public void updateVariables(RemoteContext context) { + mCachedString = context.getText(mTextId); + if (mType == -1) { + if (mFontFamilyId != -1) { + String fontFamily = context.getText(mFontFamilyId); + if (fontFamily != null) { + mType = 0; // default + if (fontFamily.equalsIgnoreCase("default")) { + mType = 0; + } else if (fontFamily.equalsIgnoreCase("sans-serif")) { + mType = 1; + } else if (fontFamily.equalsIgnoreCase("serif")) { + mType = 2; + } else if (fontFamily.equalsIgnoreCase("monospace")) { + mType = 3; + } + } + } else { + mType = 0; + } + } + mNeedsMeasure = true; + needsRepaint(); + } + + public TextLayout(Component parent, int componentId, int animationId, + float x, float y, float width, float height, + int textId, int color, float fontSize, + int fontStyle, float fontWeight, int fontFamilyId) { + super(parent, componentId, animationId, x, y, width, height); + mTextId = textId; + mColor = color; + mFontSize = fontSize; + mFontStyle = fontStyle; + mFontWeight = fontWeight; + mFontFamilyId = fontFamilyId; + } + + public TextLayout(Component parent, int componentId, int animationId, + int textId, int color, float fontSize, + int fontStyle, float fontWeight, int fontFamilyId) { + this(parent, componentId, animationId, 0, 0, 0, 0, + textId, color, fontSize, fontStyle, fontWeight, fontFamilyId); + } + + public PaintBundle mPaint = new PaintBundle(); + + @Override + public void paintingComponent(PaintContext context) { + context.save(); + context.translate(mX, mY); + mComponentModifiers.paint(context); + float tx = mPaddingLeft; + float ty = mPaddingTop; + context.translate(tx, ty); + + ////////////////////////////////////////////////////////// + // Text content + ////////////////////////////////////////////////////////// + context.savePaint(); + mPaint.reset(); + mPaint.setStyle(PaintBundle.STYLE_FILL); + mPaint.setColor(mColor); + mPaint.setTextSize(mFontSize); + mPaint.setTextStyle(mType, (int) mFontWeight, mFontStyle == 1); + context.applyPaint(mPaint); + int length = mCachedString.length(); + context.drawTextRun(mTextId, 0, length, 0, 0, mTextX, mTextY, false); + if (DEBUG) { + mPaint.setStyle(PaintBundle.STYLE_FILL_AND_STROKE); + mPaint.setColor(1f, 1F, 1F, 1F); + mPaint.setStrokeWidth(3f); + context.applyPaint(mPaint); + context.drawLine(0f, 0f, mWidth, mHeight); + context.drawLine(0f, mHeight, mWidth, 0f); + mPaint.setColor(1f, 0F, 0F, 1F); + mPaint.setStrokeWidth(1f); + context.applyPaint(mPaint); + context.drawLine(0f, 0f, mWidth, mHeight); + context.drawLine(0f, mHeight, mWidth, 0f); + } + context.restorePaint(); + ////////////////////////////////////////////////////////// + + context.translate(-tx, -ty); + context.restore(); + } + + @Override + public String toString() { + return "TEXT_LAYOUT [" + mComponentId + ":" + mAnimationId + "] (" + mX + ", " + + mY + " - " + mWidth + " x " + mHeight + ") " + mVisibility; + } + + protected String getSerializedName() { + return "TEXT_LAYOUT"; + } + + @Override + public void serializeToString(int indent, StringSerializer serializer) { + serializer.append(indent, getSerializedName() + " [" + mComponentId + + ":" + mAnimationId + "] = " + + "[" + mX + ", " + mY + ", " + mWidth + ", " + mHeight + "] " + + mVisibility + " (" + mTextId + ":\"" + mCachedString + "\")" + ); + } + + @Override + public void computeWrapSize(PaintContext context, float maxWidth, float maxHeight, + MeasurePass measure, Size size) { + context.savePaint(); + mPaint.reset(); + mPaint.setTextSize(mFontSize); + mPaint.setTextStyle(mType, (int) mFontWeight, mFontStyle == 1); + context.applyPaint(mPaint); + float[] bounds = new float[4]; + int flags = PaintContext.TEXT_MEASURE_FONT_HEIGHT; + context.getTextBounds(mTextId, 0, mCachedString.length(), flags, bounds); + context.restorePaint(); + float w = bounds[2] - bounds[0]; + float h = bounds[3] - bounds[1]; + size.setWidth(w); + mTextX = -bounds[0]; + size.setHeight(h); + mTextY = -bounds[1]; + } + + public static String name() { + return "TextLayout"; + } + + public static int id() { + return Operations.LAYOUT_TEXT; + } + + public static void apply(WireBuffer buffer, int componentId, int animationId, + int textId, int color, float fontSize, int fontStyle, + float fontWeight, int fontFamilyId) { + buffer.start(id()); + buffer.writeInt(componentId); + buffer.writeInt(animationId); + buffer.writeInt(textId); + buffer.writeInt(color); + buffer.writeFloat(fontSize); + buffer.writeInt(fontStyle); + buffer.writeFloat(fontWeight); + buffer.writeInt(fontFamilyId); + } + + public static void read(WireBuffer buffer, List<Operation> operations) { + int componentId = buffer.readInt(); + int animationId = buffer.readInt(); + int textId = buffer.readInt(); + int color = buffer.readInt(); + float fontSize = buffer.readFloat(); + int fontStyle = buffer.readInt(); + float fontWeight = buffer.readFloat(); + int fontFamilyId = buffer.readInt(); + operations.add(new TextLayout(null, componentId, animationId, textId, color, fontSize, + fontStyle, fontWeight, fontFamilyId)); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Layout Operations", id(), name()) + .description("Text layout implementation.\n\n") + .field(INT, "COMPONENT_ID", "unique id for this component") + .field(INT, "ANIMATION_ID", "id used to match components," + + " for animation purposes") + .field(INT, "COLOR", "text color") + .field(FLOAT, "FONT_SIZE", "font size") + .field(INT, "FONT_STYLE", "font style (0 = normal, 1 = italic)") + .field(FLOAT, "FONT_WEIGHT", "font weight (1-1000, normal = 400)") + .field(INT, "FONT_FAMILY_ID", "font family id"); + } + + @Override + public void write(WireBuffer buffer) { + apply(buffer, mComponentId, mAnimationId, + mTextId, mColor, mFontSize, mFontStyle, + mFontWeight, mFontFamilyId); + } +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BackgroundModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BackgroundModifierOperation.java index 6f48aee845c6..f3e6a8e0aa22 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BackgroundModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BackgroundModifierOperation.java @@ -15,12 +15,14 @@ */ package com.android.internal.widget.remotecompose.core.operations.layout.modifiers; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import com.android.internal.widget.remotecompose.core.operations.paint.PaintBundle; import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer; @@ -30,10 +32,8 @@ import java.util.List; * Component size-aware background draw */ public class BackgroundModifierOperation extends DecoratorModifierOperation { - - public static final BackgroundModifierOperation.Companion COMPANION = - new BackgroundModifierOperation.Companion(); - + private static final int OP_CODE = Operations.MODIFIER_BACKGROUND; + private static final String CLASS_NAME = "BackgroundModifierOperation"; float mX; float mY; float mWidth; @@ -62,7 +62,7 @@ public class BackgroundModifierOperation extends DecoratorModifierOperation { @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mX, mY, mWidth, mHeight, mR, mG, mB, mA, mShapeType); + apply(buffer, mX, mY, mWidth, mHeight, mR, mG, mB, mA, mShapeType); } @Override @@ -84,55 +84,50 @@ public class BackgroundModifierOperation extends DecoratorModifierOperation { return "BackgroundModifierOperation(" + mWidth + " x " + mHeight + ")"; } - public static class Companion implements CompanionOperation { - - - @Override - public String name() { - return "OrigamiBackground"; - } + public static String name() { + return CLASS_NAME; + } - @Override - public int id() { - return Operations.MODIFIER_BACKGROUND; - } + public static int id() { + return OP_CODE; + } - public void apply(WireBuffer buffer, float x, float y, float width, float height, - float r, float g, float b, float a, int shapeType) { - buffer.start(Operations.MODIFIER_BACKGROUND); - buffer.writeFloat(x); - buffer.writeFloat(y); - buffer.writeFloat(width); - buffer.writeFloat(height); - buffer.writeFloat(r); - buffer.writeFloat(g); - buffer.writeFloat(b); - buffer.writeFloat(a); - // shape type - buffer.writeInt(shapeType); - } + public static void apply(WireBuffer buffer, float x, float y, float width, float height, + float r, float g, float b, float a, int shapeType) { + buffer.start(OP_CODE); + buffer.writeFloat(x); + buffer.writeFloat(y); + buffer.writeFloat(width); + buffer.writeFloat(height); + buffer.writeFloat(r); + buffer.writeFloat(g); + buffer.writeFloat(b); + buffer.writeFloat(a); + // shape type + buffer.writeInt(shapeType); + } - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - float x = buffer.readFloat(); - float y = buffer.readFloat(); - float width = buffer.readFloat(); - float height = buffer.readFloat(); - float r = buffer.readFloat(); - float g = buffer.readFloat(); - float b = buffer.readFloat(); - float a = buffer.readFloat(); - // shape type - int shapeType = buffer.readInt(); - operations.add(new BackgroundModifierOperation(x, y, width, height, - r, g, b, a, shapeType)); - } + public static void read(WireBuffer buffer, List<Operation> operations) { + float x = buffer.readFloat(); + float y = buffer.readFloat(); + float width = buffer.readFloat(); + float height = buffer.readFloat(); + float r = buffer.readFloat(); + float g = buffer.readFloat(); + float b = buffer.readFloat(); + float a = buffer.readFloat(); + // shape type + int shapeType = buffer.readInt(); + operations.add(new BackgroundModifierOperation(x, y, width, height, + r, g, b, a, shapeType)); } + @Override public void paint(PaintContext context) { context.savePaint(); mPaint.reset(); + mPaint.setStyle(PaintBundle.STYLE_FILL); mPaint.setColor(mR, mG, mB, mA); context.applyPaint(mPaint); if (mShapeType == ShapeType.RECTANGLE) { @@ -143,4 +138,20 @@ public class BackgroundModifierOperation extends DecoratorModifierOperation { } context.restorePaint(); } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Modifier Operations", + OP_CODE, + CLASS_NAME) + .description("define the Background Modifier") + .field(FLOAT, "x", "") + .field(FLOAT, "y", "") + .field(FLOAT, "width", "") + .field(FLOAT, "height", "") + .field(FLOAT, "r", "") + .field(FLOAT, "g", "") + .field(FLOAT, "b", "") + .field(FLOAT, "a", "") + .field(FLOAT, "shapeType", ""); + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BorderModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BorderModifierOperation.java index 0b9c01b93896..4c83ec4e627e 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BorderModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BorderModifierOperation.java @@ -15,12 +15,14 @@ */ package com.android.internal.widget.remotecompose.core.operations.layout.modifiers; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import com.android.internal.widget.remotecompose.core.operations.paint.PaintBundle; import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer; @@ -30,9 +32,8 @@ import java.util.List; * Component size-aware border draw */ public class BorderModifierOperation extends DecoratorModifierOperation { - - public static final BorderModifierOperation.Companion COMPANION = - new BorderModifierOperation.Companion(); + private static final int OP_CODE = Operations.MODIFIER_BORDER; + public static final String CLASS_NAME = "BorderModifierOperation"; float mX; float mY; @@ -75,7 +76,7 @@ public class BorderModifierOperation extends DecoratorModifierOperation { @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mX, mY, mWidth, mHeight, mBorderWidth, mRoundedCorner, + apply(buffer, mX, mY, mWidth, mHeight, mBorderWidth, mRoundedCorner, mR, mG, mB, mA, mShapeType); } @@ -92,56 +93,52 @@ public class BorderModifierOperation extends DecoratorModifierOperation { + "color(" + mR + "," + mG + "," + mB + "," + mA + ")"; } - public static class Companion implements CompanionOperation { - @Override - public String name() { - return "BorderModifier"; - } + public static String name() { + return CLASS_NAME; + } - @Override - public int id() { - return Operations.MODIFIER_BORDER; - } + public static int id() { + return OP_CODE; + } - public void apply(WireBuffer buffer, float x, float y, float width, float height, - float borderWidth, float roundedCorner, - float r, float g, float b, float a, - int shapeType) { - buffer.start(Operations.MODIFIER_BORDER); - buffer.writeFloat(x); - buffer.writeFloat(y); - buffer.writeFloat(width); - buffer.writeFloat(height); - buffer.writeFloat(borderWidth); - buffer.writeFloat(roundedCorner); - buffer.writeFloat(r); - buffer.writeFloat(g); - buffer.writeFloat(b); - buffer.writeFloat(a); - // shape type - buffer.writeInt(shapeType); - } + public static void apply(WireBuffer buffer, float x, float y, float width, float height, + float borderWidth, float roundedCorner, + float r, float g, float b, float a, + int shapeType) { + buffer.start(OP_CODE); + buffer.writeFloat(x); + buffer.writeFloat(y); + buffer.writeFloat(width); + buffer.writeFloat(height); + buffer.writeFloat(borderWidth); + buffer.writeFloat(roundedCorner); + buffer.writeFloat(r); + buffer.writeFloat(g); + buffer.writeFloat(b); + buffer.writeFloat(a); + // shape type + buffer.writeInt(shapeType); + } - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - float x = buffer.readFloat(); - float y = buffer.readFloat(); - float width = buffer.readFloat(); - float height = buffer.readFloat(); - float bw = buffer.readFloat(); - float rc = buffer.readFloat(); - float r = buffer.readFloat(); - float g = buffer.readFloat(); - float b = buffer.readFloat(); - float a = buffer.readFloat(); - // shape type - int shapeType = buffer.readInt(); - operations.add(new BorderModifierOperation(x, y, width, height, bw, - rc, r, g, b, a, shapeType)); - } + public static void read(WireBuffer buffer, List<Operation> operations) { + float x = buffer.readFloat(); + float y = buffer.readFloat(); + float width = buffer.readFloat(); + float height = buffer.readFloat(); + float bw = buffer.readFloat(); + float rc = buffer.readFloat(); + float r = buffer.readFloat(); + float g = buffer.readFloat(); + float b = buffer.readFloat(); + float a = buffer.readFloat(); + // shape type + int shapeType = buffer.readInt(); + operations.add(new BorderModifierOperation(x, y, width, height, bw, + rc, r, g, b, a, shapeType)); } + @Override public void paint(PaintContext context) { context.savePaint(); @@ -161,4 +158,22 @@ public class BorderModifierOperation extends DecoratorModifierOperation { } context.restorePaint(); } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Modifier Operations", + OP_CODE, + CLASS_NAME) + .description("define the Border Modifier") + .field(FLOAT, "x", "") + .field(FLOAT, "y", "") + .field(FLOAT, "width", "") + .field(FLOAT, "height", "") + .field(FLOAT, "borderWidth", "") + .field(FLOAT, "roundedCorner", "") + .field(FLOAT, "r", "") + .field(FLOAT, "g", "") + .field(FLOAT, "b", "") + .field(FLOAT, "a", "") + .field(FLOAT, "shapeType", ""); + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ClipRectModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ClipRectModifierOperation.java index 30357af6275e..7cb7925692ab 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ClipRectModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ClipRectModifierOperation.java @@ -15,12 +15,14 @@ */ package com.android.internal.widget.remotecompose.core.operations.layout.modifiers; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import com.android.internal.widget.remotecompose.core.CoreDocument; import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; +import com.android.internal.widget.remotecompose.core.operations.layout.Component; import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer; import java.util.List; @@ -29,14 +31,11 @@ import java.util.List; * Support modifier clip with a rectangle */ public class ClipRectModifierOperation extends DecoratorModifierOperation { - - public static final ClipRectModifierOperation.Companion COMPANION = - new ClipRectModifierOperation.Companion(); - + public static final String CLASS_NAME = "ClipRectModifierOperation"; + private static final int OP_CODE = Operations.MODIFIER_CLIP_RECT; float mWidth; float mHeight; - @Override public void paint(PaintContext context) { context.clipRect(0f, 0f, mWidth, mHeight); @@ -49,7 +48,8 @@ public class ClipRectModifierOperation extends DecoratorModifierOperation { } @Override - public void onClick(float x, float y) { + public void onClick(RemoteContext context, CoreDocument document, + Component component, float x, float y) { // nothing } @@ -61,28 +61,32 @@ public class ClipRectModifierOperation extends DecoratorModifierOperation { @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer); + apply(buffer); + } + + public static String name() { + return CLASS_NAME; } - public static class Companion implements CompanionOperation { - @Override - public String name() { - return "ClipRectModifier"; - } + public static int id() { + return OP_CODE; + } + + public static void apply(WireBuffer buffer) { + buffer.start(OP_CODE); + } - @Override - public int id() { - return Operations.MODIFIER_CLIP_RECT; - } - public void apply(WireBuffer buffer) { - buffer.start(Operations.MODIFIER_CLIP_RECT); - } + public static void read(WireBuffer buffer, List<Operation> operations) { + operations.add(new ClipRectModifierOperation()); + } + - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - operations.add(new ClipRectModifierOperation()); - } + public static void documentation(DocumentationBuilder doc) { + doc.operation("Canvas Operations", + OP_CODE, + CLASS_NAME) + .description("Draw the specified round-rect"); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentModifiers.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentModifiers.java index 2ef0b9d7a56f..f55c94126001 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentModifiers.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentModifiers.java @@ -15,12 +15,15 @@ */ package com.android.internal.widget.remotecompose.core.operations.layout.modifiers; +import com.android.internal.widget.remotecompose.core.CoreDocument; import com.android.internal.widget.remotecompose.core.PaintContext; import com.android.internal.widget.remotecompose.core.PaintOperation; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.WireBuffer; import com.android.internal.widget.remotecompose.core.operations.MatrixRestore; import com.android.internal.widget.remotecompose.core.operations.MatrixSave; +import com.android.internal.widget.remotecompose.core.operations.layout.ClickModifierOperation; +import com.android.internal.widget.remotecompose.core.operations.layout.Component; import com.android.internal.widget.remotecompose.core.operations.layout.DecoratorComponent; import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer; @@ -37,6 +40,23 @@ public class ComponentModifiers extends PaintOperation implements DecoratorCompo } @Override + public void apply(RemoteContext context) { + super.apply(context); + for (ModifierOperation op : mList) { + op.apply(context); + } + } + + @Override + public String toString() { + String str = "ComponentModifiers \n"; + for (ModifierOperation modifierOperation : mList) { + str += " " + modifierOperation.toString() + "\n"; + } + return str; + } + + @Override public void write(WireBuffer buffer) { // nothing } @@ -70,7 +90,11 @@ public class ComponentModifiers extends PaintOperation implements DecoratorCompo if (op instanceof MatrixSave || op instanceof MatrixRestore) { continue; } - if (op instanceof PaintOperation) { + if (op instanceof ClickModifierOperation) { + context.translate(-tx, -ty); + ((ClickModifierOperation) op).paint(context); + context.translate(tx, ty); + } else if (op instanceof PaintOperation) { ((PaintOperation) op).paint(context); } } @@ -89,7 +113,9 @@ public class ComponentModifiers extends PaintOperation implements DecoratorCompo w -= pop.getLeft() + pop.getRight(); h -= pop.getTop() + pop.getBottom(); } - if (op instanceof DecoratorComponent) { + if (op instanceof ClickModifierOperation) { + ((DecoratorComponent) op).layout(context, width, height); + } else if (op instanceof DecoratorComponent) { ((DecoratorComponent) op).layout(context, w, h); } } @@ -99,10 +125,11 @@ public class ComponentModifiers extends PaintOperation implements DecoratorCompo mList.addAll(operations); } - public void onClick(float x, float y) { + public void onClick(RemoteContext context, CoreDocument document, + Component component, float x, float y) { for (ModifierOperation op : mList) { if (op instanceof DecoratorComponent) { - ((DecoratorComponent) op).onClick(x, y); + ((DecoratorComponent) op).onClick(context, document, component, x, y); } } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentVisibilityOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentVisibilityOperation.java new file mode 100644 index 000000000000..9c190730706a --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentVisibilityOperation.java @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget.remotecompose.core.operations.layout.modifiers; + +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; + +import com.android.internal.widget.remotecompose.core.CoreDocument; +import com.android.internal.widget.remotecompose.core.Operation; +import com.android.internal.widget.remotecompose.core.Operations; +import com.android.internal.widget.remotecompose.core.RemoteContext; +import com.android.internal.widget.remotecompose.core.VariableSupport; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; +import com.android.internal.widget.remotecompose.core.operations.layout.Component; +import com.android.internal.widget.remotecompose.core.operations.layout.DecoratorComponent; +import com.android.internal.widget.remotecompose.core.operations.layout.LayoutComponent; +import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer; + +import java.util.List; + +/** + * Allows setting visibility on a component + */ +public class ComponentVisibilityOperation implements ModifierOperation, + VariableSupport, DecoratorComponent { + private static final int OP_CODE = Operations.MODIFIER_VISIBILITY; + + int mVisibilityId; + Component.Visibility mVisibility = Component.Visibility.VISIBLE; + private LayoutComponent mParent; + + public ComponentVisibilityOperation(int id) { + mVisibilityId = id; + } + + @Override + public String toString() { + return "ComponentVisibilityOperation(" + mVisibilityId + ")"; + } + + public String serializedName() { + return "COMPONENT_VISIBILITY"; + } + + @Override + public void serializeToString(int indent, StringSerializer serializer) { + serializer.append(indent, serializedName() + " = " + mVisibilityId); + } + + @Override + public void apply(RemoteContext context) { + } + + @Override + public String deepToString(String indent) { + return (indent != null ? indent : "") + toString(); + } + + + @Override + public void write(WireBuffer buffer) { + + } + + public static void apply(WireBuffer buffer, int valueId) { + buffer.start(OP_CODE); + buffer.writeInt(valueId); + } + + public static void read(WireBuffer buffer, List<Operation> operations) { + int valueId = buffer.readInt(); + operations.add(new ComponentVisibilityOperation(valueId)); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Layout Operations", OP_CODE, "ComponentVisibility") + .description("This operation allows setting a component" + + "visibility from a provided value") + .field(INT, "VALUE_ID", "Value ID representing the visibility"); + } + + @Override + public void registerListening(RemoteContext context) { + context.listensTo(mVisibilityId, this); + } + + @Override + public void updateVariables(RemoteContext context) { + int visibility = context.getInteger(mVisibilityId); + if (visibility == Component.Visibility.VISIBLE.ordinal()) { + mVisibility = Component.Visibility.VISIBLE; + } else if (visibility == Component.Visibility.GONE.ordinal()) { + mVisibility = Component.Visibility.GONE; + } else if (visibility == Component.Visibility.INVISIBLE.ordinal()) { + mVisibility = Component.Visibility.INVISIBLE; + } else { + mVisibility = Component.Visibility.GONE; + } + if (mParent != null) { + mParent.setVisibility(mVisibility); + } + } + + public void setParent(LayoutComponent parent) { + mParent = parent; + } + + @Override + public void layout(RemoteContext context, float width, float height) { + + } + + @Override + public void onClick(RemoteContext context, CoreDocument document, + Component component, float x, float y) { + + } +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DecoratorModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DecoratorModifierOperation.java index bf9b27b647db..70a572845c23 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DecoratorModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DecoratorModifierOperation.java @@ -15,7 +15,10 @@ */ package com.android.internal.widget.remotecompose.core.operations.layout.modifiers; +import com.android.internal.widget.remotecompose.core.CoreDocument; import com.android.internal.widget.remotecompose.core.PaintOperation; +import com.android.internal.widget.remotecompose.core.RemoteContext; +import com.android.internal.widget.remotecompose.core.operations.layout.Component; import com.android.internal.widget.remotecompose.core.operations.layout.DecoratorComponent; /** @@ -26,7 +29,8 @@ public abstract class DecoratorModifierOperation extends PaintOperation implements ModifierOperation, DecoratorComponent { @Override - public void onClick(float x, float y) { + public void onClick(RemoteContext context, CoreDocument document, + Component component, float x, float y) { // nothing } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DimensionModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DimensionModifierOperation.java index 04e943105ef0..f085ffb6c73b 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DimensionModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DimensionModifierOperation.java @@ -15,33 +15,33 @@ */ package com.android.internal.widget.remotecompose.core.operations.layout.modifiers; -import com.android.internal.widget.remotecompose.core.CompanionOperation; -import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.RemoteContext; -import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.VariableSupport; +import com.android.internal.widget.remotecompose.core.operations.Utils; import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer; -import java.util.List; - /** * Base class for dimension modifiers */ -public class DimensionModifierOperation implements ModifierOperation { - - public static final DimensionModifierOperation.Companion COMPANION = - new DimensionModifierOperation.Companion(0, "DIMENSION"); +public abstract class DimensionModifierOperation implements ModifierOperation, VariableSupport { public enum Type { EXACT, FILL, WRAP, WEIGHT, INTRINSIC_MIN, INTRINSIC_MAX; static Type fromInt(int value) { switch (value) { - case 0: return EXACT; - case 1: return FILL; - case 2: return WRAP; - case 3: return WEIGHT; - case 4: return INTRINSIC_MIN; - case 5: return INTRINSIC_MAX; + case 0: + return EXACT; + case 1: + return FILL; + case 2: + return WRAP; + case 3: + return WEIGHT; + case 4: + return INTRINSIC_MIN; + case 5: + return INTRINSIC_MAX; } return EXACT; } @@ -49,10 +49,11 @@ public class DimensionModifierOperation implements ModifierOperation { Type mType = Type.EXACT; float mValue = Float.NaN; + float mOutValue = Float.NaN; public DimensionModifierOperation(Type type, float value) { mType = type; - mValue = value; + mOutValue = mValue = value; } public DimensionModifierOperation(Type type) { @@ -63,6 +64,25 @@ public class DimensionModifierOperation implements ModifierOperation { this(Type.EXACT, value); } + @Override + public void updateVariables(RemoteContext context) { + if (mType == Type.EXACT) { + mOutValue = (Float.isNaN(mValue)) + ? context.getFloat(Utils.idFromNan(mValue)) : mValue; + } + + } + + @Override + public void registerListening(RemoteContext context) { + if (mType == Type.EXACT) { + if (Float.isNaN(mValue)) { + context.listensTo(Utils.idFromNan(mValue), this); + } + } + + } + public boolean hasWeight() { return mType == Type.WEIGHT; @@ -81,17 +101,13 @@ public class DimensionModifierOperation implements ModifierOperation { } public float getValue() { - return mValue; + return mOutValue; } public void setValue(float value) { - this.mValue = value; + mOutValue = mValue = value; } - @Override - public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mType.ordinal(), mValue); - } public String serializedName() { return "DIMENSION"; @@ -117,43 +133,4 @@ public class DimensionModifierOperation implements ModifierOperation { public String toString() { return "DimensionModifierOperation(" + mValue + ")"; } - - public static class Companion implements CompanionOperation { - - int mOperation; - String mName; - - public Companion(int operation, String name) { - mOperation = operation; - mName = name; - } - - @Override - public String name() { - return mName; - } - - @Override - public int id() { - return mOperation; - } - - public void apply(WireBuffer buffer, int type, float value) { - buffer.start(mOperation); - buffer.writeInt(type); - buffer.writeFloat(value); - } - - public Operation construct(Type type, float value) { - return null; - } - - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - Type type = Type.fromInt(buffer.readInt()); - float value = buffer.readFloat(); - Operation op = construct(type, value); - operations.add(op); - } - } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightModifierOperation.java index 81173c3e4343..a0f576a412f8 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightModifierOperation.java @@ -15,21 +15,48 @@ */ package com.android.internal.widget.remotecompose.core.operations.layout.modifiers; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; + +import java.util.List; /** * Set the height dimension on a component */ public class HeightModifierOperation extends DimensionModifierOperation { + private static final int OP_CODE = Operations.MODIFIER_HEIGHT; + public static final String CLASS_NAME = "HeightModifierOperation"; + + public static String name() { + return CLASS_NAME; + } + + public static int id() { + return OP_CODE; + } + + public static void apply(WireBuffer buffer, int type, float value) { + buffer.start(OP_CODE); + buffer.writeInt(type); + buffer.writeFloat(value); + } - public static final DimensionModifierOperation.Companion COMPANION = - new DimensionModifierOperation.Companion(Operations.MODIFIER_HEIGHT, "WIDTH") { - @Override - public Operation construct(DimensionModifierOperation.Type type, float value) { - return new HeightModifierOperation(type, value); - } - }; + public static void read(WireBuffer buffer, List<Operation> operations) { + Type type = Type.fromInt(buffer.readInt()); + float value = buffer.readFloat(); + Operation op = new HeightModifierOperation(type, value); + operations.add(op); + } + + @Override + public void write(WireBuffer buffer) { + apply(buffer, mType.ordinal(), mValue); + } public HeightModifierOperation(Type type, float value) { super(type, value); @@ -52,4 +79,13 @@ public class HeightModifierOperation extends DimensionModifierOperation { public String serializedName() { return "HEIGHT"; } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Modifier Operations", + OP_CODE, + CLASS_NAME) + .description("define the animation") + .field(INT, "type", "") + .field(FLOAT, "value", ""); + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostActionOperation.java new file mode 100644 index 000000000000..d405b2b2a6a7 --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostActionOperation.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget.remotecompose.core.operations.layout.modifiers; + +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; + +import com.android.internal.widget.remotecompose.core.CoreDocument; +import com.android.internal.widget.remotecompose.core.Operation; +import com.android.internal.widget.remotecompose.core.Operations; +import com.android.internal.widget.remotecompose.core.RemoteContext; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; +import com.android.internal.widget.remotecompose.core.operations.layout.ActionOperation; +import com.android.internal.widget.remotecompose.core.operations.layout.Component; +import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer; + +import java.util.List; + +/** + * Capture a host action information. This can be triggered on eg. a click. + */ +public class HostActionOperation implements ActionOperation { + private static final int OP_CODE = Operations.HOST_ACTION; + + int mActionId = -1; + + public HostActionOperation(int id) { + mActionId = id; + } + + @Override + public String toString() { + return "HostActionOperation(" + mActionId + ")"; + } + + public int getActionId() { + return mActionId; + } + + public String serializedName() { + return "HOST_ACTION"; + } + + @Override + public void serializeToString(int indent, StringSerializer serializer) { + serializer.append(indent, serializedName() + " = " + mActionId); + } + + @Override + public void apply(RemoteContext context) { + } + + @Override + public String deepToString(String indent) { + return (indent != null ? indent : "") + toString(); + } + + + @Override + public void write(WireBuffer buffer) { + + } + + @Override + public void runAction(RemoteContext context, CoreDocument document, + Component component, float x, float y) { + context.runAction(mActionId, ""); + } + + public static void apply(WireBuffer buffer, int actionId) { + buffer.start(OP_CODE); + buffer.writeInt(actionId); + } + + public static void read(WireBuffer buffer, List<Operation> operations) { + int actionId = buffer.readInt(); + operations.add(new HostActionOperation(actionId)); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Layout Operations", OP_CODE, "HostAction") + .description("Host action. This operation represents a host action") + .field(INT, "ACTION_ID", "Host Action ID"); + } + +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostNamedActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostNamedActionOperation.java new file mode 100644 index 000000000000..35f202bd6ed3 --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostNamedActionOperation.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget.remotecompose.core.operations.layout.modifiers; + +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; + +import com.android.internal.widget.remotecompose.core.CoreDocument; +import com.android.internal.widget.remotecompose.core.Operation; +import com.android.internal.widget.remotecompose.core.Operations; +import com.android.internal.widget.remotecompose.core.RemoteContext; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; +import com.android.internal.widget.remotecompose.core.operations.layout.ActionOperation; +import com.android.internal.widget.remotecompose.core.operations.layout.Component; +import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer; + +import java.util.List; + +/** + * Capture a host action information. This can be triggered on eg. a click. + */ +public class HostNamedActionOperation implements ActionOperation { + private static final int OP_CODE = Operations.HOST_NAMED_ACTION; + + int mTextId = -1; + + public HostNamedActionOperation(int id) { + mTextId = id; + } + + @Override + public String toString() { + return "HostNamedActionOperation(" + mTextId + ")"; + } + + public String serializedName() { + return "HOST_NAMED_ACTION"; + } + + @Override + public void serializeToString(int indent, StringSerializer serializer) { + serializer.append(indent, serializedName() + " = " + mTextId); + } + + @Override + public void apply(RemoteContext context) { + } + + @Override + public String deepToString(String indent) { + return (indent != null ? indent : "") + toString(); + } + + + @Override + public void write(WireBuffer buffer) { + + } + + @Override + public void runAction(RemoteContext context, CoreDocument document, + Component component, float x, float y) { + context.runNamedAction(mTextId); + } + + public static void apply(WireBuffer buffer, int textId) { + buffer.start(OP_CODE); + buffer.writeInt(textId); + } + + public static void read(WireBuffer buffer, List<Operation> operations) { + int textId = buffer.readInt(); + operations.add(new HostNamedActionOperation(textId)); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Layout Operations", OP_CODE, "HostNamedAction") + .description("Host Named action. This operation represents a host action") + .field(INT, "TEXT_ID", "Named Host Action Text ID"); + } + +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/PaddingModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/PaddingModifierOperation.java index 5ea6a97dd127..668db3b71027 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/PaddingModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/PaddingModifierOperation.java @@ -15,11 +15,13 @@ */ package com.android.internal.widget.remotecompose.core.operations.layout.modifiers; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer; import java.util.List; @@ -29,10 +31,8 @@ import java.util.List; * Padding modifiers can be chained and will impact following modifiers. */ public class PaddingModifierOperation implements ModifierOperation { - - public static final PaddingModifierOperation.Companion COMPANION = - new PaddingModifierOperation.Companion(); - + private static final int OP_CODE = Operations.MODIFIER_PADDING; + public static final String CLASS_NAME = "PaddingModifierOperation"; float mLeft; float mTop; float mRight; @@ -79,7 +79,7 @@ public class PaddingModifierOperation implements ModifierOperation { @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mLeft, mTop, mRight, mBottom); + apply(buffer, mLeft, mTop, mRight, mBottom); } @Override @@ -103,33 +103,39 @@ public class PaddingModifierOperation implements ModifierOperation { + ", " + mRight + ", " + mBottom + ")"; } - public static class Companion implements CompanionOperation { - @Override - public String name() { - return "PaddingModifierOperation"; - } - - @Override - public int id() { - return Operations.MODIFIER_PADDING; - } - - public void apply(WireBuffer buffer, - float left, float top, float right, float bottom) { - buffer.start(Operations.MODIFIER_PADDING); - buffer.writeFloat(left); - buffer.writeFloat(top); - buffer.writeFloat(right); - buffer.writeFloat(bottom); - } - - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - float left = buffer.readFloat(); - float top = buffer.readFloat(); - float right = buffer.readFloat(); - float bottom = buffer.readFloat(); - operations.add(new PaddingModifierOperation(left, top, right, bottom)); - } + public static String name() { + return CLASS_NAME; + } + + public static int id() { + return Operations.MODIFIER_PADDING; + } + + public static void apply(WireBuffer buffer, + float left, float top, float right, float bottom) { + buffer.start(Operations.MODIFIER_PADDING); + buffer.writeFloat(left); + buffer.writeFloat(top); + buffer.writeFloat(right); + buffer.writeFloat(bottom); + } + + public static void read(WireBuffer buffer, List<Operation> operations) { + float left = buffer.readFloat(); + float top = buffer.readFloat(); + float right = buffer.readFloat(); + float bottom = buffer.readFloat(); + operations.add(new PaddingModifierOperation(left, top, right, bottom)); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Modifier Operations", + OP_CODE, + CLASS_NAME) + .description("define the Padding Modifier") + .field(FLOAT, "left", "") + .field(FLOAT, "top", "") + .field(FLOAT, "right", "") + .field(FLOAT, "bottom", ""); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/RoundedClipRectModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/RoundedClipRectModifierOperation.java index 9c57c6ab4e89..9b662bf5eca7 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/RoundedClipRectModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/RoundedClipRectModifierOperation.java @@ -15,30 +15,72 @@ */ package com.android.internal.widget.remotecompose.core.operations.layout.modifiers; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT; + +import com.android.internal.widget.remotecompose.core.CoreDocument; import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; import com.android.internal.widget.remotecompose.core.RemoteContext; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import com.android.internal.widget.remotecompose.core.operations.DrawBase4; +import com.android.internal.widget.remotecompose.core.operations.layout.Component; import com.android.internal.widget.remotecompose.core.operations.layout.DecoratorComponent; import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer; +import java.util.List; + /** - * Support clip with a rectangle + * Support clip with a rounded rectangle */ public class RoundedClipRectModifierOperation extends DrawBase4 implements ModifierOperation, DecoratorComponent { + public static final int OP_CODE = Operations.MODIFIER_ROUNDED_CLIP_RECT; + public static final String CLASS_NAME = "RoundedClipRectModifierOperation"; + + public static void read(WireBuffer buffer, List<Operation> operations) { + Maker m = RoundedClipRectModifierOperation::new; + read(m, buffer, operations); + } + + public static int id() { + return OP_CODE; + } + + public static String name() { + return CLASS_NAME; + } + + + protected void write(WireBuffer buffer, + float v1, + float v2, + float v3, + float v4) { + apply(buffer, v1, v2, v3, v4); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Modifier Operations", + id(), + "RoundedClipRectModifierOperation") + .description("clip with rectangle") + .field(FLOAT, "topStart", + "The topStart radius of the rectangle to " + + "intersect with the current clip") + .field(FLOAT, "topEnd", + "The topEnd radius of the rectangle to " + + "intersect with the current clip") + .field(FLOAT, "bottomStart", + "The bottomStart radius of the rectangle to " + + "intersect with the current clip") + .field(FLOAT, "bottomEnd", + "The bottomEnd radius of the rectangle to " + + "intersect with the current clip"); + } + - public static final Companion COMPANION = - new Companion(Operations.MODIFIER_ROUNDED_CLIP_RECT) { - @Override - public Operation construct(float x1, - float y1, - float x2, - float y2) { - return new RoundedClipRectModifierOperation(x1, y1, x2, y2); - } - }; float mWidth; float mHeight; @@ -49,7 +91,7 @@ public class RoundedClipRectModifierOperation extends DrawBase4 float bottomStart, float bottomEnd) { super(topStart, topEnd, bottomStart, bottomEnd); - mName = "ModifierRoundedClipRect"; + mName = CLASS_NAME; } @Override @@ -64,15 +106,33 @@ public class RoundedClipRectModifierOperation extends DrawBase4 } @Override - public void onClick(float x, float y) { + public void onClick(RemoteContext context, CoreDocument document, + Component component, float x, float y) { // nothing } @Override public void serializeToString(int indent, StringSerializer serializer) { serializer.append( - indent, "ROUND_CLIP = [" + mWidth + ", " + mHeight + indent, "ROUNDED_CLIP_RECT = [" + mWidth + ", " + mHeight + ", " + mX1 + ", " + mY1 + ", " + mX2 + ", " + mY2 + "]"); } + + /** + * Writes out the rounded rect clip to the buffer + * + * @param buffer buffer to write to + * @param topStart topStart radius + * @param topEnd topEnd radius + * @param bottomStart bottomStart radius + * @param bottomEnd bottomEnd radius + */ + public static void apply(WireBuffer buffer, + float topStart, + float topEnd, + float bottomStart, + float bottomEnd) { + write(buffer, OP_CODE, topStart, topEnd, bottomStart, bottomEnd); + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerChangeActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerChangeActionOperation.java new file mode 100644 index 000000000000..3f19c9b1bc4b --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerChangeActionOperation.java @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget.remotecompose.core.operations.layout.modifiers; + +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; + +import com.android.internal.widget.remotecompose.core.CoreDocument; +import com.android.internal.widget.remotecompose.core.Operation; +import com.android.internal.widget.remotecompose.core.Operations; +import com.android.internal.widget.remotecompose.core.RemoteContext; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; +import com.android.internal.widget.remotecompose.core.operations.layout.ActionOperation; +import com.android.internal.widget.remotecompose.core.operations.layout.Component; +import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer; + +import java.util.List; + +/** + * Apply a value change on an integer variable. + */ +public class ValueIntegerChangeActionOperation implements ActionOperation { + private static final int OP_CODE = Operations.VALUE_INTEGER_CHANGE_ACTION; + + int mTargetValueId = -1; + int mValue = -1; + + public ValueIntegerChangeActionOperation(int id, int value) { + mTargetValueId = id; + mValue = value; + } + + @Override + public String toString() { + return "ValueChangeActionOperation(" + mTargetValueId + ")"; + } + + public String serializedName() { + return "VALUE_INTEGER_CHANGE"; + } + + @Override + public void serializeToString(int indent, StringSerializer serializer) { + serializer.append(indent, serializedName() + + " = " + mTargetValueId + " -> " + mValue); + } + + @Override + public void apply(RemoteContext context) { + } + + @Override + public String deepToString(String indent) { + return (indent != null ? indent : "") + toString(); + } + + + @Override + public void write(WireBuffer buffer) { + + } + + @Override + public void runAction(RemoteContext context, CoreDocument document, + Component component, float x, float y) { + context.overrideInteger(mTargetValueId, mValue); + } + + public static void apply(WireBuffer buffer, int valueId, int value) { + buffer.start(OP_CODE); + buffer.writeInt(valueId); + buffer.writeInt(value); + } + + public static void read(WireBuffer buffer, List<Operation> operations) { + int valueId = buffer.readInt(); + int value = buffer.readInt(); + operations.add(new ValueIntegerChangeActionOperation(valueId, value)); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Layout Operations", OP_CODE, "ValueIntegerChangeActionOperation") + .description("ValueIntegerChange action. " + + " This operation represents a value change for the given id") + .field(INT, "TARGET_VALUE_ID", "Value ID") + .field(INT, "VALUE", "integer value to be assigned to the target") + ; + } + +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueStringChangeActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueStringChangeActionOperation.java new file mode 100644 index 000000000000..e2542e529383 --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueStringChangeActionOperation.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget.remotecompose.core.operations.layout.modifiers; + +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; + +import com.android.internal.widget.remotecompose.core.CoreDocument; +import com.android.internal.widget.remotecompose.core.Operation; +import com.android.internal.widget.remotecompose.core.Operations; +import com.android.internal.widget.remotecompose.core.RemoteContext; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; +import com.android.internal.widget.remotecompose.core.operations.layout.ActionOperation; +import com.android.internal.widget.remotecompose.core.operations.layout.Component; +import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer; + +import java.util.List; + +/** + * Apply a value change on a string variable. + */ +public class ValueStringChangeActionOperation implements ActionOperation { + private static final int OP_CODE = Operations.VALUE_STRING_CHANGE_ACTION; + + int mTargetValueId = -1; + int mValueId = -1; + + public ValueStringChangeActionOperation(int id, int value) { + mTargetValueId = id; + mValueId = value; + } + + @Override + public String toString() { + return "ValueChangeActionOperation(" + mTargetValueId + ")"; + } + + public int getActionId() { + return mTargetValueId; + } + + public String serializedName() { + return "VALUE_CHANGE"; + } + + @Override + public void serializeToString(int indent, StringSerializer serializer) { + serializer.append(indent, serializedName() + " = " + mTargetValueId + " -> " + mValueId); + } + + @Override + public void apply(RemoteContext context) { + } + + @Override + public String deepToString(String indent) { + return (indent != null ? indent : "") + toString(); + } + + @Override + public void write(WireBuffer buffer) { + + } + + @Override + public void runAction(RemoteContext context, CoreDocument document, + Component component, float x, float y) { + context.overrideText(mTargetValueId, mValueId); + } + + public static void apply(WireBuffer buffer, int valueId, int value) { + buffer.start(OP_CODE); + buffer.writeInt(valueId); + buffer.writeInt(value); + } + + public static void read(WireBuffer buffer, List<Operation> operations) { + int valueId = buffer.readInt(); + int value = buffer.readInt(); + operations.add(new ValueStringChangeActionOperation(valueId, value)); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Layout Operations", OP_CODE, "ValueStringChangeActionOperation") + .description("ValueStrin gChange action. " + + " This operation represents a String change (referenced by id) " + + "for the given string id") + .field(INT, "TARGET_ID", "Target Value ID") + .field(INT, "VALUE_ID", "Value ID to be assigned to the target " + + "value as a string") + ; + } + +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthModifierOperation.java index c46c8d70c0b1..7fd5e51add18 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthModifierOperation.java @@ -15,26 +15,54 @@ */ package com.android.internal.widget.remotecompose.core.operations.layout.modifiers; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.FLOAT; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; + +import java.util.List; /** * Set the width dimension on a component */ public class WidthModifierOperation extends DimensionModifierOperation { + private static final int OP_CODE = Operations.MODIFIER_WIDTH; + public static final String CLASS_NAME = "WidthModifierOperation"; + + + public static String name() { + return CLASS_NAME; + } + + public static int id() { + return OP_CODE; + } - public static final DimensionModifierOperation.Companion COMPANION = - new DimensionModifierOperation.Companion(Operations.MODIFIER_WIDTH, "WIDTH") { - @Override - public Operation construct(DimensionModifierOperation.Type type, float value) { - return new WidthModifierOperation(type, value); - } - }; + public static void apply(WireBuffer buffer, int type, float value) { + buffer.start(OP_CODE); + buffer.writeInt(type); + buffer.writeFloat(value); + } + + public static void read(WireBuffer buffer, List<Operation> operations) { + Type type = Type.fromInt(buffer.readInt()); + float value = buffer.readFloat(); + Operation op = new WidthModifierOperation(type, value); + operations.add(op); + } public WidthModifierOperation(Type type, float value) { super(type, value); } + @Override + public void write(WireBuffer buffer) { + apply(buffer, mType.ordinal(), mValue); + } + public WidthModifierOperation(Type type) { super(type); } @@ -52,4 +80,13 @@ public class WidthModifierOperation extends DimensionModifierOperation { public String serializedName() { return "WIDTH"; } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Modifier Operations", + OP_CODE, + CLASS_NAME) + .description("define the animation") + .field(INT, "type", "") + .field(FLOAT, "value", ""); + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/paint/PaintBundle.java b/core/java/com/android/internal/widget/remotecompose/core/operations/paint/PaintBundle.java index 818619223fb3..6c8049a97f1e 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/paint/PaintBundle.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/paint/PaintBundle.java @@ -714,7 +714,7 @@ public class PaintBundle { * @param a alpha (0.0 to 1.0) */ public void setColor(float r, float g, float b, float a) { - setColor((int) r * 255, (int) g * 255, (int) b * 255, (int) a * 255); + setColor((int) (r * 255), (int) (g * 255), (int) (b * 255), (int) (a * 255)); } /** diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/AnimatedFloatExpression.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/AnimatedFloatExpression.java index 616048d424ec..5b295eb700ec 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/AnimatedFloatExpression.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/AnimatedFloatExpression.java @@ -15,12 +15,15 @@ */ package com.android.internal.widget.remotecompose.core.operations.utilities; +import static com.android.internal.widget.remotecompose.core.operations.utilities.NanMap.ID_REGION_ARRAY; +import static com.android.internal.widget.remotecompose.core.operations.utilities.NanMap.ID_REGION_MASK; + /** * high performance floating point expression evaluator used in animation */ public class AnimatedFloatExpression { static IntMap<String> sNames = new IntMap<>(); - public static final int OFFSET = 0x100; + public static final int OFFSET = 0x310_000; public static final float ADD = asNan(OFFSET + 1); public static final float SUB = asNan(OFFSET + 2); public static final float MUL = asNan(OFFSET + 3); @@ -57,11 +60,18 @@ public class AnimatedFloatExpression { public static final float CEIL = asNan(OFFSET + 31); - public static final float LAST_OP = 31; + // Array ops + public static final float A_DEREF = asNan(OFFSET + 32); + public static final float A_MAX = asNan(OFFSET + 33); + public static final float A_MIN = asNan(OFFSET + 34); + public static final float A_SUM = asNan(OFFSET + 35); + public static final float A_AVG = asNan(OFFSET + 36); + public static final float A_LEN = asNan(OFFSET + 37); + public static final int LAST_OP = OFFSET + 37; - public static final float VAR1 = asNan(OFFSET + 27); - public static final float VAR2 = asNan(OFFSET + 28); + public static final float VAR1 = asNan(OFFSET + 38); + public static final float VAR2 = asNan(OFFSET + 39); // TODO CLAMP, CBRT, DEG, RAD, EXPM1, CEIL, FLOOR private static final float FP_PI = (float) Math.PI; @@ -71,16 +81,23 @@ public class AnimatedFloatExpression { float[] mStack; float[] mLocalStack = new float[128]; float[] mVar; + CollectionsAccess mCollectionsAccess; /** * is float a math operator + * * @param v * @return */ public static boolean isMathOperator(float v) { if (Float.isNaN(v)) { int pos = fromNaN(v); - return pos > OFFSET && pos <= OFFSET + LAST_OP; + // a data variable is a type of math operator for expressions + // it dereference to a value + if (NanMap.isDataVariable(v)) { + return false; + } + return pos > OFFSET && pos <= LAST_OP; } return false; } @@ -89,8 +106,21 @@ public class AnimatedFloatExpression { int eval(int sp); } + /** * Evaluate a float expression + * This system works by processing an Array of float (float[]) + * in reverse polish notation (rpn) + * Within that array some floats are commands + * they are encoded within an NaN. + * After processing the array the last item on the array is returned. + * The system supports variables allowing expressions like. + * sin(sqrt(x*x+y*y))/sqrt(x*x+y*y) + * Where x & y are passe as parameters + * Examples: + * (1+2) (1, 2, ADD) adds two numbers returns 3 + * eval(new float[]{ Var1, Var * } + * * @param exp * @param var * @return @@ -110,8 +140,46 @@ public class AnimatedFloatExpression { return mStack[sp]; } + + /** + * Evaluate a float expression + * + * @param ca + * @param exp + * @param var + * @return + */ + public float eval(CollectionsAccess ca, float[] exp, float... var) { + mStack = exp; + mVar = var; + mCollectionsAccess = ca; + int sp = -1; + + for (int i = 0; i < mStack.length; i++) { + float v = mStack[i]; + if (Float.isNaN(v)) { + int id = fromNaN(v); + if ((id & ID_REGION_MASK) != ID_REGION_ARRAY) { + sp = mOps[id - OFFSET].eval(sp); + } else { + mStack[++sp] = v; + } + } else { + mStack[++sp] = v; + } + } + return mStack[sp]; + } + + + private int dereference(CollectionsAccess ca, int id, int sp) { + mStack[sp] = ca.getFloatValue(id, (int) (mStack[sp])); + return sp; + } + /** * Evaluate a float expression + * * @param exp * @param len * @param var @@ -135,6 +203,7 @@ public class AnimatedFloatExpression { /** * Evaluate a float expression + * * @param exp * @param var * @return @@ -283,6 +352,58 @@ public class AnimatedFloatExpression { mStack[sp] = (float) Math.ceil(mStack[sp]); return sp; }, + (sp) -> { // A_DEREF + int id = fromNaN(mStack[sp]); + mStack[sp] = mCollectionsAccess.getFloatValue(id, (int) (mStack[sp - 1])); + return sp - 1; + }, + (sp) -> { // A_MAX + int id = fromNaN(mStack[sp]); + float[] array = mCollectionsAccess.getFloats(id); + float max = array[0]; + for (int i = 1; i < array.length; i++) { + max = Math.max(max, array[i]); + } + mStack[sp] = max; + return sp; + }, + (sp) -> { // A_MIN + int id = fromNaN(mStack[sp]); + float[] array = mCollectionsAccess.getFloats(id); + float max = array[0]; + for (int i = 1; i < array.length; i++) { + max = Math.max(max, array[i]); + } + mStack[sp] = max; + return sp; + }, + (sp) -> { // A_SUM + int id = fromNaN(mStack[sp]); + float[] array = mCollectionsAccess.getFloats(id); + float sum = 0; + for (int i = 0; i < array.length; i++) { + sum += array[i]; + } + mStack[sp] = sum; + return sp; + }, + (sp) -> { // A_AVG + int id = fromNaN(mStack[sp]); + float[] array = mCollectionsAccess.getFloats(id); + float sum = 0; + for (int i = 0; i < array.length; i++) { + sum += array[i]; + } + mStack[sp] = sum / array.length; + return sp; + }, + (sp) -> { // A_LEN + int id = fromNaN(mStack[sp]); + mStack[sp] = mCollectionsAccess.getFloatsLength(id); + return sp; + }, + + (sp) -> { // first var = mStack[sp] = mVar[0]; return sp; @@ -331,6 +452,14 @@ public class AnimatedFloatExpression { sNames.put(k++, "deg"); sNames.put(k++, "rad"); sNames.put(k++, "ceil"); + + sNames.put(k++, "A_DEREF"); + sNames.put(k++, "A_MAX"); + sNames.put(k++, "A_MIN"); + sNames.put(k++, "A_SUM"); + sNames.put(k++, "A_AVG"); + sNames.put(k++, "A_LEN"); + sNames.put(k++, "a[0]"); sNames.put(k++, "a[1]"); sNames.put(k++, "a[2]"); @@ -338,6 +467,7 @@ public class AnimatedFloatExpression { /** * given a float command return its math name (e.g sin, cos etc.) + * * @param f * @return */ @@ -348,6 +478,7 @@ public class AnimatedFloatExpression { /** * Convert an expression encoded as an array of floats int ot a string + * * @param exp * @param labels * @return @@ -360,15 +491,21 @@ public class AnimatedFloatExpression { if (isMathOperator(v)) { s.append(toMathName(v)); } else { + int id = fromNaN(v); + String idString = (id > ID_REGION_ARRAY) ? ("A_" + (id & 0xFFFFF)) : "" + id; s.append("["); - s.append(fromNaN(v)); + s.append(idString); s.append("]"); } } else { - if (labels[i] != null) { + if (labels != null && labels[i] != null) { s.append(labels[i]); + if (!labels[i].contains("_")) { + s.append(v); + } + } else { + s.append(v); } - s.append(v); } s.append(" "); } @@ -423,6 +560,7 @@ public class AnimatedFloatExpression { /** * to be used by parser to determine if command is infix + * * @param n * @return */ @@ -432,6 +570,7 @@ public class AnimatedFloatExpression { /** * Convert an id into a NaN object + * * @param v * @return */ @@ -441,12 +580,12 @@ public class AnimatedFloatExpression { /** * Get ID from a NaN float + * * @param v * @return */ public static int fromNaN(float v) { int b = Float.floatToRawIntBits(v); - return b & 0xFFFFF; + return b & 0x7FFFFF; } - } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/ArrayAccess.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/ArrayAccess.java new file mode 100644 index 000000000000..4c7cc3889bcb --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/ArrayAccess.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget.remotecompose.core.operations.utilities; + +public interface ArrayAccess { + float getFloatValue(int index); + float[] getFloats(); + int getFloatsLength(); + + default int getIntValue(int index) { + return (int) getFloatValue(index); + } +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/CollectionsAccess.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/CollectionsAccess.java new file mode 100644 index 000000000000..9e5312676aa4 --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/CollectionsAccess.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget.remotecompose.core.operations.utilities; + +public interface CollectionsAccess { + float getFloatValue(int id, int index); + float[] getFloats(int id); + int getFloatsLength(int id); + + default int getIntValue(int id, int index) { + return (int) getFloatValue(id, index); + } +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/ColorUtils.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/ColorUtils.java index 0ea28a8bb900..fb96ceffa58a 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/ColorUtils.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/ColorUtils.java @@ -65,4 +65,17 @@ public class ColorUtils { } return 0; } + + /** + * Utility function to create a color as an int + * + * @param r red + * @param g green + * @param b blue + * @param a alpha + * @return int packed color + */ + public static int createColor(int r, int g, int b, int a) { + return (a << 24) | (r << 16) | (g << 8) | b; + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntegerExpressionEvaluator.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntegerExpressionEvaluator.java index a4fce80cf843..ae61ec1e5eec 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntegerExpressionEvaluator.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntegerExpressionEvaluator.java @@ -17,6 +17,9 @@ package com.android.internal.widget.remotecompose.core.operations.utilities; /** * High performance Integer expression evaluator + * + * The evaluation is based on int opMask, int[]exp + * exp[i] is an operator if (opMask*(1 << i) != 0) */ public class IntegerExpressionEvaluator { static IntMap<String> sNames = new IntMap<>(); @@ -64,11 +67,11 @@ public class IntegerExpressionEvaluator { } /** - * Evaluate a float expression - * - * @param exp - * @param var - * @return + * Evaluate an integer expression + * @param mask bits that are operators + * @param exp rpn sequence of values and operators + * @param var variables if the expression is a function + * @return return the results of evaluating the expression */ public int eval(int mask, int[] exp, int... var) { mStack = exp; @@ -86,12 +89,12 @@ public class IntegerExpressionEvaluator { } /** - * Evaluate a int expression - * - * @param exp - * @param len - * @param var - * @return + * Evaluate a integer expression + * @param mask bits that are operators + * @param exp rpn sequence of values and operators + * @param len the number of values in the expression + * @param var variables if the expression is a function + * @return return the results of evaluating the expression */ public int eval(int mask, int[] exp, int len, int... var) { System.arraycopy(exp, 0, mLocalStack, 0, len); @@ -111,18 +114,18 @@ public class IntegerExpressionEvaluator { /** * Evaluate a int expression - * - * @param exp - * @param var - * @return + * @param opMask bits that are operators + * @param exp rpn sequence of values and operators + * @param var variables if the expression is a function + * @return return the results of evaluating the expression */ - public int evalDB(int mask, int[] exp, int... var) { + public int evalDB(int opMask, int[] exp, int... var) { mStack = exp; mVar = var; int sp = -1; for (int i = 0; i < exp.length; i++) { int v = mStack[i]; - if (((1 << i) & mask) != 0) { + if (((1 << i) & opMask) != 0) { System.out.print(" " + sNames.get((v - OFFSET))); sp = mOps[v - OFFSET].eval(sp); } else { @@ -281,8 +284,8 @@ public class IntegerExpressionEvaluator { /** * given a int command return its math name (e.g sin, cos etc.) * - * @param f - * @return + * @param f the numerical value of the function + offset + * @return the math name of the function */ public static String toMathName(int f) { int id = f - OFFSET; @@ -290,18 +293,19 @@ public class IntegerExpressionEvaluator { } /** - * Convert an expression encoded as an array of ints int ot a string + * Convert an expression encoded as an array of ints int to a string * - * @param exp - * @param labels + * @param opMask bits that are operators + * @param exp rpn sequence of values and operators + * @param labels String that represent the variable names * @return */ - public static String toString(int mask, int[] exp, String[] labels) { + public static String toString(int opMask, int[] exp, String[] labels) { StringBuilder s = new StringBuilder(); for (int i = 0; i < exp.length; i++) { int v = exp[i]; - if (((1 << i) & mask) != 0) { + if (((1 << i) & opMask) != 0) { if (v < OFFSET) { s.append(toMathName(v)); } else { @@ -323,18 +327,18 @@ public class IntegerExpressionEvaluator { /** * Convert an expression encoded as an array of ints int ot a string * - * @param mask bit mask of operators vs commands - * @param exp - * @return + * @param opMask bit mask of operators vs commands + * @param exp rpn sequence of values and operators + * @return string representation of the expression */ - public static String toString(int mask, int[] exp) { + public static String toString(int opMask, int[] exp) { StringBuilder s = new StringBuilder(); - s.append(Integer.toBinaryString(mask)); + s.append(Integer.toBinaryString(opMask)); s.append(" : "); for (int i = 0; i < exp.length; i++) { int v = exp[i]; - if (((1 << i) & mask) != 0) { + if (((1 << i) & opMask) != 0) { if (v > OFFSET) { s.append(" "); s.append(toMathName(v)); @@ -353,16 +357,15 @@ public class IntegerExpressionEvaluator { /** * This creates an infix string expression - * @param mask The bits that are operators + * @param opMask The bits that are operators * @param exp the array of expressions * @return infix string */ - public static String toStringInfix(int mask, int[] exp) { - return toString(mask, exp, exp.length - 1); + public static String toStringInfix(int opMask, int[] exp) { + return toString(opMask, exp, exp.length - 1); } static String toString(int mask, int[] exp, int sp) { - String[] str = new String[exp.length]; if (((1 << sp) & mask) != 0) { int id = exp[sp] - OFFSET; switch (NO_OF_OPS[id]) { @@ -418,11 +421,11 @@ public class IntegerExpressionEvaluator { /** * is it an id or operation - * @param mask the bits that mark elements as an operation + * @param opMask the bits that mark elements as an operation * @param i the bit to check * @return true if the bit is 1 */ - public static boolean isOperation(int mask, int i) { - return ((1 << i) & mask) != 0; + public static boolean isOperation(int opMask, int i) { + return ((1 << i) & opMask) != 0; } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/NanMap.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/NanMap.java index f4cd504d650f..1e669c6b2e35 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/NanMap.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/NanMap.java @@ -19,20 +19,25 @@ import com.android.internal.widget.remotecompose.core.operations.Utils; /** * This defines the major id maps and ranges used by remote compose - * Generally ids ranging from 0 ... FFF (4095) are for ids + * Generally ids ranging from 1 ... 7FFFFF (4095) are for ids + * The data range is divided int to bits + * 0xxxxx are allocated for Predefined Global System Variables + * 1xxxxx are allocated to normal variables + * 2xxxxx are allocated to List&MAPS (Arrays of stuff) + * 3xxxxx are allocated to path & float operations + * 4xxxxx,5xxxxx,7xxxxx are reserved for future use * 0x1000-0x1100 are used for path operations in PathData * 0x1100-0x1200 are used for math operations in Animated float * 0x */ public class NanMap { - - public static final int MOVE = 0x1000; - public static final int LINE = 0x1001; - public static final int QUADRATIC = 0x1002; - public static final int CONIC = 0x1003; - public static final int CUBIC = 0x1004; - public static final int CLOSE = 0x1005; - public static final int DONE = 0x1006; + public static final int MOVE = 0x300_000; + public static final int LINE = 0x300_001; + public static final int QUADRATIC = 0x300_002; + public static final int CONIC = 0x300_003; + public static final int CUBIC = 0x300_004; + public static final int CLOSE = 0x300_005; + public static final int DONE = 0x300_006; public static final float MOVE_NAN = Utils.asNan(MOVE); public static final float LINE_NAN = Utils.asNan(LINE); public static final float QUADRATIC_NAN = Utils.asNan(QUADRATIC); @@ -41,31 +46,46 @@ public class NanMap { public static final float CLOSE_NAN = Utils.asNan(CLOSE); public static final float DONE_NAN = Utils.asNan(DONE); - /** - * - */ - public static final float ADD = asNan(0x1100); - public static final float SUB = asNan(0x1101); - public static final float MUL = asNan(0x1102); - public static final float DIV = asNan(0x1103); - public static final float MOD = asNan(0x1104); - public static final float MIN = asNan(0x1105); - public static final float MAX = asNan(0x1106); - public static final float POW = asNan(0x1107); + public static boolean isSystemVariable(float value) { + return (fromNaN(value) >> 20) == 0; + } + + public static boolean isNormalVariable(float value) { + return (fromNaN(value) >> 20) == 1; + } + + public static boolean isDataVariable(float value) { + return (fromNaN(value) >> 20) == 2; + } + + public static boolean isOperationVariable(float value) { + return (fromNaN(value) >> 20) == 3; + } + + public static final int START_VAR = (1 << 20) + 42; + public static final int START_ARRAY = (2 << 20) + 42; + public static final int TYPE_SYSTEM = 0; + public static final int TYPE_VARIABLE = 1; + public static final int TYPE_ARRAY = 2; + public static final int TYPE_OPERATION = 3; + public static final int ID_REGION_MASK = 0x700000; + public static final int ID_REGION_ARRAY = 0x200000; /** * Get ID from Nan float + * * @param v * @return */ public static int fromNaN(float v) { int b = Float.floatToRawIntBits(v); - return b & 0xFFFFF; + return b & 0x7FFFFF; } /** * Given id return as a Nan float + * * @param v * @return */ diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/FloatAnimation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/FloatAnimation.java index 4f484de1045e..98dbf0048abd 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/FloatAnimation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/easing/FloatAnimation.java @@ -51,6 +51,7 @@ public class FloatAnimation extends Easing { } public FloatAnimation() { + mEasingCurve = new CubicEasing(mType); } public FloatAnimation(float... description) { @@ -86,21 +87,26 @@ public class FloatAnimation extends Easing { count++; } if (spec != null) { + count++; } if (spec != null || type != CUBIC_STANDARD) { count++; count += (spec == null) ? 0 : spec.length; } - if (duration != 1 || count > 0) { - count++; - } + if (!Float.isNaN(initialValue)) { count++; } if (!Float.isNaN(wrap)) { count++; } + if (duration != 1 || count > 0) { + count++; + } + if (!Float.isNaN(wrap) || !Float.isNaN(initialValue)) { + count++; + } float[] ret = new float[count]; int pos = 0; int specLen = (spec == null) ? 0 : spec.length; diff --git a/core/java/com/android/internal/widget/remotecompose/core/types/BooleanConstant.java b/core/java/com/android/internal/widget/remotecompose/core/types/BooleanConstant.java index 1051192441dd..9045bcbd2e06 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/types/BooleanConstant.java +++ b/core/java/com/android/internal/widget/remotecompose/core/types/BooleanConstant.java @@ -15,11 +15,14 @@ */ package com.android.internal.widget.remotecompose.core.types; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.BYTE; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import java.util.List; @@ -27,6 +30,7 @@ import java.util.List; * Used to represent a boolean */ public class BooleanConstant implements Operation { + private static final int OP_CODE = Operations.DATA_BOOLEAN; boolean mValue = false; private int mId; @@ -37,7 +41,7 @@ public class BooleanConstant implements Operation { @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mId, mValue); + apply(buffer, mId, mValue); } @Override @@ -55,42 +59,43 @@ public class BooleanConstant implements Operation { return "BooleanConstant[" + mId + "] = " + mValue + ""; } - public static final Companion COMPANION = new Companion(); - - public static class Companion implements CompanionOperation { - private Companion() { - } - - @Override - public String name() { - return "OrigamiBoolean"; - } - - @Override - public int id() { - return Operations.DATA_BOOLEAN; - } - - /** - * Writes out the operation to the buffer - * - * @param buffer - * @param id - * @param value - */ - public void apply(WireBuffer buffer, int id, boolean value) { - buffer.start(Operations.DATA_BOOLEAN); - buffer.writeInt(id); - buffer.writeBoolean(value); - } - - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int id = buffer.readInt(); - - boolean value = buffer.readBoolean(); - operations.add(new BooleanConstant(id, value)); - } + public static String name() { + return "OrigamiBoolean"; + } + + public static int id() { + return Operations.DATA_BOOLEAN; + } + + /** + * Writes out the operation to the buffer + * + * @param buffer + * @param id + * @param value + */ + public static void apply(WireBuffer buffer, int id, boolean value) { + buffer.start(OP_CODE); + buffer.writeInt(id); + buffer.writeBoolean(value); + } + + public static void read(WireBuffer buffer, List<Operation> operations) { + int id = buffer.readInt(); + + boolean value = buffer.readBoolean(); + operations.add(new BooleanConstant(id, value)); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Expressions Operations", + OP_CODE, + "BooleanConstant") + .description("A boolean and its associated id") + .field(INT, "id", "id of Int") + .field(BYTE, "value", + "8-bit 0 or 1"); + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/types/IntegerConstant.java b/core/java/com/android/internal/widget/remotecompose/core/types/IntegerConstant.java index ceb323629e98..90faf52f2362 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/types/IntegerConstant.java +++ b/core/java/com/android/internal/widget/remotecompose/core/types/IntegerConstant.java @@ -15,11 +15,13 @@ */ package com.android.internal.widget.remotecompose.core.types; -import com.android.internal.widget.remotecompose.core.CompanionOperation; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; + import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; import java.util.List; @@ -38,7 +40,7 @@ public class IntegerConstant implements Operation { @Override public void write(WireBuffer buffer) { - COMPANION.apply(buffer, mId, mValue); + apply(buffer, mId, mValue); } @Override @@ -56,41 +58,42 @@ public class IntegerConstant implements Operation { return "IntegerConstant[" + mId + "] = " + mValue + ""; } - public static final Companion COMPANION = new Companion(); - - public static class Companion implements CompanionOperation { - private Companion() { - } - - @Override - public String name() { - return "IntegerConstant"; - } - - @Override - public int id() { - return Operations.DATA_INT; - } - - /** - * Writes out the operation to the buffer - * - * @param buffer - * @param textId - * @param value - */ - public void apply(WireBuffer buffer, int textId, int value) { - buffer.start(Operations.DATA_INT); - buffer.writeInt(textId); - buffer.writeInt(value); - } - - @Override - public void read(WireBuffer buffer, List<Operation> operations) { - int id = buffer.readInt(); - - int value = buffer.readInt(); - operations.add(new IntegerConstant(id, value)); - } + public static String name() { + return "IntegerConstant"; + } + + public static int id() { + return Operations.DATA_INT; + } + + /** + * Writes out the operation to the buffer + * + * @param buffer + * @param textId + * @param value + */ + public static void apply(WireBuffer buffer, int textId, int value) { + buffer.start(Operations.DATA_INT); + buffer.writeInt(textId); + buffer.writeInt(value); + } + + public static void read(WireBuffer buffer, List<Operation> operations) { + int id = buffer.readInt(); + + int value = buffer.readInt(); + operations.add(new IntegerConstant(id, value)); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Expressions Operations", + id(), + "IntegerConstant") + .description("A integer and its associated id") + .field(INT, "id", "id of Int") + .field(INT, "value", + "32-bit int value"); + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/types/LongConstant.java b/core/java/com/android/internal/widget/remotecompose/core/types/LongConstant.java new file mode 100644 index 000000000000..70402cf45eae --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/types/LongConstant.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget.remotecompose.core.types; + +import static com.android.internal.widget.remotecompose.core.documentation.Operation.INT; +import static com.android.internal.widget.remotecompose.core.documentation.Operation.LONG; + +import com.android.internal.widget.remotecompose.core.Operation; +import com.android.internal.widget.remotecompose.core.Operations; +import com.android.internal.widget.remotecompose.core.RemoteContext; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; + +import java.util.List; + +/** + * Used to represent a long + */ +public class LongConstant implements Operation { + private static final int OP_CODE = Operations.DATA_LONG; + long mValue; + private int mId; + + public LongConstant(int id, long value) { + mId = id; + mValue = value; + } + + @Override + public void write(WireBuffer buffer) { + apply(buffer, mId, mValue); + } + + @Override + public void apply(RemoteContext context) { + } + + @Override + public String deepToString(String indent) { + return toString(); + } + + @Override + public String toString() { + return "LongConstant[" + mId + "] = " + mValue + ""; + } + + /** + * Writes out the operation to the buffer + * + * @param buffer + * @param id + * @param value + */ + public static void apply(WireBuffer buffer, int id, long value) { + buffer.start(OP_CODE); + buffer.writeInt(id); + buffer.writeLong(value); + } + + public static void read(WireBuffer buffer, List<Operation> operations) { + int id = buffer.readInt(); + + long value = buffer.readLong(); + operations.add(new LongConstant(id, value)); + } + + public static void documentation(DocumentationBuilder doc) { + doc.operation("Expressions Operations", + OP_CODE, + "LongConstant") + .description("A boolean and its associated id") + .field(INT, "id", "id of Int") + .field(LONG, "value", + "The long Value"); + + } + +} diff --git a/core/java/com/android/internal/widget/remotecompose/player/RemoteComposeDocument.java b/core/java/com/android/internal/widget/remotecompose/player/RemoteComposeDocument.java index 65a337e672b8..e32f8239d7ef 100644 --- a/core/java/com/android/internal/widget/remotecompose/player/RemoteComposeDocument.java +++ b/core/java/com/android/internal/widget/remotecompose/player/RemoteComposeDocument.java @@ -35,6 +35,10 @@ public class RemoteComposeDocument { mDocument.initFromBuffer(buffer); } + public RemoteComposeDocument(CoreDocument document) { + mDocument = document; + } + public CoreDocument getDocument() { return mDocument; } @@ -122,5 +126,16 @@ public class RemoteComposeDocument { public Component getComponent(int id) { return mDocument.getComponent(id); } + + public void invalidate() { + mDocument.invalidateMeasure(); + } + + public String[] getStats() { + if (mDocument == null) { + return new String[0]; + } + return mDocument.getStats(); + } } diff --git a/core/java/com/android/internal/widget/remotecompose/player/RemoteComposePlayer.java b/core/java/com/android/internal/widget/remotecompose/player/RemoteComposePlayer.java index b2406bf69ec8..3d78680bff0a 100644 --- a/core/java/com/android/internal/widget/remotecompose/player/RemoteComposePlayer.java +++ b/core/java/com/android/internal/widget/remotecompose/player/RemoteComposePlayer.java @@ -66,6 +66,10 @@ public class RemoteComposePlayer extends FrameLayout { } } + public RemoteComposeDocument getDocument() { + return mInner.getDocument(); + } + public void setDocument(RemoteComposeDocument value) { if (value != null) { if (value.canBeDisplayed( @@ -151,6 +155,84 @@ public class RemoteComposePlayer extends FrameLayout { addView(mInner, layoutParams); } + /** + * Set an override for a string resource + * + * @param domain domain (SYSTEM or USER) + * @param name name of the string + * @param content content of the string + */ + public void setLocalString(String domain, String name, String content) { + mInner.setLocalString(domain + ":" + name, content); + } + + /** + * Clear the override of the given string + * + * @param domain domain (SYSTEM or USER) + * @param name name of the string + */ + public void clearLocalString(String domain, String name) { + mInner.clearLocalString(domain + ":" + name); + } + + /** + * Set an override for a user domain string resource + * + * @param name name of the string + * @param content content of the string + */ + public void setUserLocalString(String name, String content) { + mInner.setLocalString("USER:" + name, content); + } + + /** + * Set an override for a user domain int resource + * + * @param name name of the int + * @param value value of the int + */ + public void setUserLocalInt(String name, int value) { + mInner.setLocalInt("USER:" + name, value); + } + + /** + * Clear the override of the given user string + * + * @param name name of the string + */ + public void clearUserLocalString(String name) { + mInner.clearLocalString("USER:" + name); + } + + /** + * Clear the override of the given user int + * + * @param name name of the int + */ + public void clearUserLocalInt(String name) { + mInner.clearLocalInt("USER:" + name); + } + + /** + * Set an override for a system domain string resource + * + * @param name name of the string + * @param content content of the string + */ + public void setSystemLocalString(String name, String content) { + mInner.setLocalString("SYSTEM:" + name, content); + } + + /** + * Clear the override of the given system string + * + * @param name name of the string + */ + public void clearSystemLocalString(String name) { + mInner.clearLocalString("SYSTEM:" + name); + } + public interface ClickCallbacks { void click(int id, String metadata); } @@ -409,4 +491,7 @@ public class RemoteComposePlayer extends FrameLayout { return color; } } + + } + diff --git a/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPaintContext.java b/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPaintContext.java index e01dd17ae0ea..4416cf76295c 100644 --- a/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPaintContext.java +++ b/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPaintContext.java @@ -210,19 +210,30 @@ public class AndroidPaintContext extends PaintContext { } @Override - public void getTextBounds(int textId, int start, int end, boolean monospace, float[] bounds) { + public void getTextBounds(int textId, int start, int end, int flags, float[] bounds) { String str = getText(textId); if (end == -1) { end = str.length(); } + Paint.FontMetrics metrics = mPaint.getFontMetrics(); mPaint.getTextBounds(str, start, end, mTmpRect); bounds[0] = mTmpRect.left; - bounds[1] = mTmpRect.top; - bounds[2] = monospace ? (mPaint.measureText(str, start, end) - mTmpRect.left) - : mTmpRect.right; - bounds[3] = mTmpRect.bottom; + + if ((flags & PaintContext.TEXT_MEASURE_MONOSPACE_WIDTH) != 0) { + bounds[2] = mPaint.measureText(str, start, end) - mTmpRect.left; + } else { + bounds[2] = mTmpRect.right; + } + + if ((flags & PaintContext.TEXT_MEASURE_FONT_HEIGHT) != 0) { + bounds[1] = Math.round(metrics.ascent); + bounds[3] = Math.round(metrics.bottom); + } else { + bounds[1] = mTmpRect.top; + bounds[3] = mTmpRect.bottom; + } } @Override @@ -236,6 +247,9 @@ public class AndroidPaintContext extends PaintContext { boolean rtl) { String textToPaint = getText(textID); + if (textToPaint == null) { + return; + } if (end == -1) { if (start != 0) { textToPaint = textToPaint.substring(start); diff --git a/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidRemoteContext.java b/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidRemoteContext.java index 5a87c7083c9d..c98937530897 100644 --- a/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidRemoteContext.java +++ b/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidRemoteContext.java @@ -23,6 +23,7 @@ import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.VariableSupport; import com.android.internal.widget.remotecompose.core.operations.FloatExpression; import com.android.internal.widget.remotecompose.core.operations.ShaderData; +import com.android.internal.widget.remotecompose.core.operations.utilities.ArrayAccess; import java.util.HashMap; @@ -52,7 +53,7 @@ class AndroidRemoteContext extends RemoteContext { @Override public void loadPathData(int instanceId, float[] floatPath) { if (!mRemoteComposeState.containsId(instanceId)) { - mRemoteComposeState.cache(instanceId, floatPath); + mRemoteComposeState.cacheData(instanceId, floatPath); } } @@ -75,6 +76,40 @@ class AndroidRemoteContext extends RemoteContext { mVarNameHashMap.put(varName, new VarName(varName, varId, varType)); } + @Override + public void setNamedStringOverride(String stringName, String value) { + if (mVarNameHashMap.get(stringName) != null) { + int id = mVarNameHashMap.get(stringName).mId; + overrideText(id, value); + } + } + + @Override + public void clearNamedStringOverride(String stringName) { + if (mVarNameHashMap.get(stringName) != null) { + int id = mVarNameHashMap.get(stringName).mId; + clearDataOverride(id); + } + mVarNameHashMap.put(stringName, null); + } + + @Override + public void setNamedIntegerOverride(String stringName, int value) { + if (mVarNameHashMap.get(stringName) != null) { + int id = mVarNameHashMap.get(stringName).mId; + overrideInt(id, value); + } + } + + @Override + public void clearNamedIntegerOverride(String integerName) { + if (mVarNameHashMap.get(integerName) != null) { + int id = mVarNameHashMap.get(integerName).mId; + clearIntegerOverride(id); + } + mVarNameHashMap.put(integerName, null); + } + /** * Override a color to force it to be the color provided * @@ -85,6 +120,23 @@ class AndroidRemoteContext extends RemoteContext { int id = mVarNameHashMap.get(colorName).mId; mRemoteComposeState.overrideColor(id, color); } + + @Override + public void addCollection(int id, ArrayAccess collection) { + mRemoteComposeState.addCollection(id, collection); + } + + @Override + public void runAction(int id, String metadata) { + mDocument.performClick(id); + } + + @Override + public void runNamedAction(int id) { + String text = getText(id); + mDocument.runNamedAction(text); + } + /** * Decode a byte array into an image and cache it using the given imageId * @@ -97,19 +149,35 @@ class AndroidRemoteContext extends RemoteContext { public void loadBitmap(int imageId, int width, int height, byte[] bitmap) { if (!mRemoteComposeState.containsId(imageId)) { Bitmap image = BitmapFactory.decodeByteArray(bitmap, 0, bitmap.length); - mRemoteComposeState.cache(imageId, image); + mRemoteComposeState.cacheData(imageId, image); } } @Override public void loadText(int id, String text) { if (!mRemoteComposeState.containsId(id)) { - mRemoteComposeState.cache(id, text); + mRemoteComposeState.cacheData(id, text); } else { - mRemoteComposeState.update(id, text); + mRemoteComposeState.updateData(id, text); } } + public void overrideText(int id, String text) { + mRemoteComposeState.overrideData(id, text); + } + + public void overrideInt(int id, int value) { + mRemoteComposeState.overrideInteger(id, value); + } + + public void clearDataOverride(int id) { + mRemoteComposeState.clearDataOverride(id); + } + + public void clearIntegerOverride(int id) { + mRemoteComposeState.clearIntegerOverride(id); + } + @Override public String getText(int id) { return (String) mRemoteComposeState.getFromId(id); @@ -125,6 +193,14 @@ class AndroidRemoteContext extends RemoteContext { mRemoteComposeState.updateInteger(id, value); } + public void overrideInteger(int id, int value) { + mRemoteComposeState.overrideInteger(id, value); + } + + public void overrideText(int id, int valueId) { + String text = getText(valueId); + overrideText(id, text); + } @Override public void loadColor(int id, int color) { @@ -133,12 +209,12 @@ class AndroidRemoteContext extends RemoteContext { @Override public void loadAnimatedFloat(int id, FloatExpression animatedFloat) { - mRemoteComposeState.cache(id, animatedFloat); + mRemoteComposeState.cacheData(id, animatedFloat); } @Override public void loadShader(int id, ShaderData value) { - mRemoteComposeState.cache(id, value); + mRemoteComposeState.cacheData(id, value); } @Override @@ -187,5 +263,6 @@ class AndroidRemoteContext extends RemoteContext { String metadata = (String) mRemoteComposeState.getFromId(metadataId); mDocument.addClickArea(id, contentDescription, left, top, right, bottom, metadata); } + } diff --git a/core/java/com/android/internal/widget/remotecompose/player/platform/FloatsToPath.java b/core/java/com/android/internal/widget/remotecompose/player/platform/FloatsToPath.java index 7a8542712cbf..d75232a6557e 100644 --- a/core/java/com/android/internal/widget/remotecompose/player/platform/FloatsToPath.java +++ b/core/java/com/android/internal/widget/remotecompose/player/platform/FloatsToPath.java @@ -19,7 +19,6 @@ import static com.android.internal.widget.remotecompose.core.operations.Utils.id import android.graphics.Path; import android.graphics.PathMeasure; -import android.os.Build; import com.android.internal.widget.remotecompose.core.operations.PathData; @@ -58,13 +57,11 @@ public class FloatsToPath { break; case PathData.CONIC: { i += 3; - if (Build.VERSION.SDK_INT >= 34) { // REMOVE IN PLATFORM - path.conicTo( - floatPath[i + 0], floatPath[i + 1], - floatPath[i + 2], floatPath[i + 3], - floatPath[i + 4] - ); - } + path.conicTo( + floatPath[i + 0], floatPath[i + 1], + floatPath[i + 2], floatPath[i + 3], + floatPath[i + 4] + ); i += 5; } break; diff --git a/core/java/com/android/internal/widget/remotecompose/player/platform/RemoteComposeCanvas.java b/core/java/com/android/internal/widget/remotecompose/player/platform/RemoteComposeCanvas.java index 0d7f97ac37c9..f91e15818471 100644 --- a/core/java/com/android/internal/widget/remotecompose/player/platform/RemoteComposeCanvas.java +++ b/core/java/com/android/internal/widget/remotecompose/player/platform/RemoteComposeCanvas.java @@ -41,6 +41,7 @@ public class RemoteComposeCanvas extends FrameLayout implements View.OnAttachSta int mTheme = Theme.LIGHT; boolean mInActionDown = false; boolean mDebug = false; + boolean mHasClickAreas = false; Point mActionDownPoint = new Point(0, 0); AndroidRemoteContext mARContext = new AndroidRemoteContext(); @@ -85,6 +86,7 @@ public class RemoteComposeCanvas extends FrameLayout implements View.OnAttachSta mDocument = value; mDocument.initializeContext(mARContext); setContentDescription(mDocument.getDocument().getContentDescription()); + updateClickAreas(); requestLayout(); invalidate(); } @@ -94,23 +96,33 @@ public class RemoteComposeCanvas extends FrameLayout implements View.OnAttachSta if (mDocument == null) { return; } - Set<CoreDocument.ClickAreaRepresentation> clickAreas = mDocument - .getDocument().getClickAreas(); - removeAllViews(); - for (CoreDocument.ClickAreaRepresentation area : clickAreas) { - ClickAreaView viewArea = new ClickAreaView(getContext(), mDebug, - area.getId(), area.getContentDescription(), - area.getMetadata()); - int w = (int) area.width(); - int h = (int) area.height(); - FrameLayout.LayoutParams param = new FrameLayout.LayoutParams(w, h); - param.width = w; - param.height = h; - param.leftMargin = (int) area.getLeft(); - param.topMargin = (int) area.getTop(); - viewArea.setOnClickListener(view1 - -> mDocument.getDocument().performClick(area.getId())); - addView(viewArea, param); + updateClickAreas(); + } + + private void updateClickAreas() { + if (USE_VIEW_AREA_CLICK && mDocument != null) { + mHasClickAreas = false; + Set<CoreDocument.ClickAreaRepresentation> clickAreas = mDocument + .getDocument().getClickAreas(); + removeAllViews(); + for (CoreDocument.ClickAreaRepresentation area : clickAreas) { + ClickAreaView viewArea = new ClickAreaView(getContext(), mDebug, + area.getId(), area.getContentDescription(), + area.getMetadata()); + int w = (int) area.width(); + int h = (int) area.height(); + FrameLayout.LayoutParams param = new FrameLayout.LayoutParams(w, h); + param.width = w; + param.height = h; + param.leftMargin = (int) area.getLeft(); + param.topMargin = (int) area.getTop(); + viewArea.setOnClickListener(view1 + -> mDocument.getDocument().performClick(area.getId())); + addView(viewArea, param); + } + if (!clickAreas.isEmpty()) { + mHasClickAreas = true; + } } } @@ -133,6 +145,38 @@ public class RemoteComposeCanvas extends FrameLayout implements View.OnAttachSta mARContext.setNamedColorOverride(colorName, colorValue); } + public RemoteComposeDocument getDocument() { + return mDocument; + } + + public void setLocalString(String name, String content) { + mARContext.setNamedStringOverride(name, content); + if (mDocument != null) { + mDocument.invalidate(); + } + } + + public void clearLocalString(String name) { + mARContext.clearNamedStringOverride(name); + if (mDocument != null) { + mDocument.invalidate(); + } + } + + public void setLocalInt(String name, int content) { + mARContext.setNamedIntegerOverride(name, content); + if (mDocument != null) { + mDocument.invalidate(); + } + } + + public void clearLocalInt(String name) { + mARContext.clearNamedIntegerOverride(name); + if (mDocument != null) { + mDocument.invalidate(); + } + } + public interface ClickCallbacks { void click(int id, String metadata); } @@ -153,7 +197,7 @@ public class RemoteComposeCanvas extends FrameLayout implements View.OnAttachSta } public boolean onTouchEvent(MotionEvent event) { - if (USE_VIEW_AREA_CLICK) { + if (USE_VIEW_AREA_CLICK && mHasClickAreas) { return super.onTouchEvent(event); } switch (event.getActionMasked()) { @@ -180,11 +224,13 @@ public class RemoteComposeCanvas extends FrameLayout implements View.OnAttachSta @Override public boolean performClick() { - if (USE_VIEW_AREA_CLICK) { + if (USE_VIEW_AREA_CLICK && mHasClickAreas) { return super.performClick(); } - mDocument.getDocument().onClick((float) mActionDownPoint.x, (float) mActionDownPoint.y); + mDocument.getDocument().onClick(mARContext, + (float) mActionDownPoint.x, (float) mActionDownPoint.y); super.performClick(); + invalidate(); return true; } @@ -213,9 +259,10 @@ public class RemoteComposeCanvas extends FrameLayout implements View.OnAttachSta if (mDocument == null) { return; } + int preWidth = getWidth(); + int preHeight = getHeight(); int w = measureDimension(widthMeasureSpec, mDocument.getWidth()); int h = measureDimension(heightMeasureSpec, mDocument.getHeight()); - mDocument.getDocument().invalidateMeasure(); if (!USE_VIEW_AREA_CLICK) { if (mDocument.getDocument().getContentSizing() == RootContentBehavior.SIZING_SCALE) { @@ -225,6 +272,9 @@ public class RemoteComposeCanvas extends FrameLayout implements View.OnAttachSta } } setMeasuredDimension(w, h); + if (preWidth != w || preHeight != h) { + mDocument.getDocument().invalidateMeasure(); + } } private int mCount; |